package com.yungu.swift.order.service.impl;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.dubbo.config.annotation.Service;
import com.google.common.collect.Lists;
import com.yungu.swift.assets.driver.model.dto.CarDto;
import com.yungu.swift.assets.driver.model.dto.CarModelValuationDto;
import com.yungu.swift.assets.driver.model.dto.DriverDto;
import com.yungu.swift.assets.driver.model.dto.DriverStatusCycleDto;
import com.yungu.swift.assets.driver.model.vo.DriverSameWayInfoVo;
import com.yungu.swift.assets.driver.model.vo.DriverVo;
import com.yungu.swift.assets.driver.model.vo.QueueDriverVo;
import com.yungu.swift.assets.driver.service.CarModelValuationService;
import com.yungu.swift.assets.driver.service.CarService;
import com.yungu.swift.assets.driver.service.DriverQueueService;
import com.yungu.swift.assets.driver.service.DriverService;
import com.yungu.swift.assets.driver.service.DriverStatusCycleService;
import com.yungu.swift.assets.passenger.model.dto.PassengerDto;
import com.yungu.swift.assets.passenger.service.PassengerService;
import com.yungu.swift.autoconfig.lock.RedisLock;
import com.yungu.swift.autoconfig.redis.RedisCacheService;
import com.yungu.swift.autoconfig.redis.RedisStringCacheService;
import com.yungu.swift.base.ResponseData;
import com.yungu.swift.base.model.config.DriverConfig;
import com.yungu.swift.constants.CommonConstant;
import com.yungu.swift.constants.DriverConstant;
import com.yungu.swift.constants.OrderConstant;
import com.yungu.swift.lbs.model.Coordinate;
import com.yungu.swift.lbs.model.DriverPoint;
import com.yungu.swift.lbs.model.vo.DistanceVo;
import com.yungu.swift.lbs.service.DistanceService;
import com.yungu.swift.lbs.service.LocationService;
import com.yungu.swift.order.config.ApplicationConfig;
import com.yungu.swift.order.consts.Constants;
import com.yungu.swift.order.dao.OrderDetailMapper;
import com.yungu.swift.order.dao.OrderEvaluateMapper;
import com.yungu.swift.order.dao.OrderFareMapper;
import com.yungu.swift.order.dao.OrderMapper;
import com.yungu.swift.order.helper.OrderAssignHelper;
import com.yungu.swift.order.helper.OrderHelper;
import com.yungu.swift.order.helper.OrderPushHelper;
import com.yungu.swift.order.helper.chain.AssignScoreHandler;
import com.yungu.swift.order.helper.chain.CurrentDayOrderCountHandler;
import com.yungu.swift.order.helper.chain.DriverDistanceHandler;
import com.yungu.swift.order.helper.chain.DriverPreviousOrderHandler;
import com.yungu.swift.order.helper.chain.DriverScoreHandler;
import com.yungu.swift.order.helper.chain.EmptyHandler;
import com.yungu.swift.order.helper.model.AssignScoreParam;
import com.yungu.swift.order.model.dto.OrderDetailDto;
import com.yungu.swift.order.model.dto.OrderDto;
import com.yungu.swift.order.model.dto.OrderFareDto;
import com.yungu.swift.order.model.dto.OrderOperateLogDto;
import com.yungu.swift.order.model.param.AdminAssOrCloseParam;
import com.yungu.swift.order.model.param.CrosstownAssignOrderParam;
import com.yungu.swift.order.model.param.CrosstownOrderParam;
import com.yungu.swift.order.model.param.JoinOrderParam;
import com.yungu.swift.order.model.param.MergeAssignParam;
import com.yungu.swift.order.model.param.SecretNoParam;
import com.yungu.swift.order.model.vo.AdminChildOrderInfoVo;
import com.yungu.swift.order.model.vo.CrosstownOrderAssignVo;
import com.yungu.swift.order.model.vo.CrosstownWaitStartOrderVo;
import com.yungu.swift.order.model.vo.JsonOrderDetailVo;
import com.yungu.swift.order.model.vo.OrderAssignScheduleTaskVo;
import com.yungu.swift.order.processor.CrosstownOrderProcessor;
import com.yungu.swift.order.service.OrderAssignService;
import com.yungu.swift.order.service.OrderDetailService;
import com.yungu.swift.order.service.OrderFareService;
import com.yungu.swift.order.service.OrderJoinService;
import com.yungu.swift.order.service.OrderOperateLogService;
import com.yungu.swift.order.service.OrderRiskControlService;
import com.yungu.swift.order.service.OrderSecretNoService;
import com.yungu.swift.order.service.OrderService;
import com.yungu.swift.order.thread.driver.status.DriverStatusCycleRunnable;
import com.yungu.swift.order.thread.inform.InformThreadPoolUtil;
import com.yungu.swift.order.thread.inform.OrderEvent;
import com.yungu.swift.order.thread.inform.OrderStatusInformThread;
import com.yungu.swift.order.thread.order.OrderHandleThreadPoolUtil;
import com.yungu.swift.order.thread.socket.CyclePushMessage;
import com.yungu.swift.order.thread.socket.CyclePushOrderThread;
import com.yungu.swift.order.utils.CommonUtils;
import com.yungu.swift.order.utils.MessageContentUtils;
import com.yungu.swift.order.utils.PushContentUtils;
import com.yungu.swift.order.utils.SendMessageUtils;
import com.yungu.swift.order.utils.ThreadExecutorUtils;
import com.yungu.swift.socket.push.model.PushContent;
import com.yungu.swift.socket.push.service.PushService;
import com.yungu.swift.system.sys.model.dto.SysAssignConfigDto;
import com.yungu.swift.system.sys.model.dto.SysBusinessOperateLogDto;
import com.yungu.swift.system.sys.model.dto.SysWayDto;
import com.yungu.swift.system.sys.model.enums.SysBusinessOperateEnum;
import com.yungu.swift.system.sys.model.vo.BusinessDetailVo;
import com.yungu.swift.system.sys.service.SysAssignConfigService;
import com.yungu.swift.system.sys.service.SysBusinessCityService;
import com.yungu.swift.system.sys.service.SysBusinessOperateLogService;
import com.yungu.swift.system.sys.service.SysWayService;
import com.yungu.swift.utils.CalendarUtil;
import com.yungu.swift.utils.DateUtils;
import com.yungu.swift.utils.JsonUtils;
import com.yungu.swift.utils.LocationUtils;
import com.yungu.swift.utils.MapUtils;
import com.yungu.swift.utils.ParamUtil;
import com.yungu.swift.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.math.BigDecimal;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.yungu.swift.order.helper.OrderHelper.findOrder;
import static com.yungu.swift.order.helper.OrderHelper.findOrderDetail;
import static com.yungu.swift.order.helper.OrderHelper.saveOrUpdate;
import static com.yungu.swift.order.helper.OrderHelper.saveOrUpdateStaticDataOnOrderMatch;
import static com.yungu.swift.order.helper.OrderHelper.saveOrderInfo;
import static com.yungu.swift.order.helper.OrderHelper.uploadTextResult;
import static com.yungu.swift.order.helper.OrderPushHelper.pushListOrder2Dri;
import static com.yungu.swift.order.helper.OrderPushHelper.pushOrder2Dri;
import static com.yungu.swift.order.helper.OrderPushHelper.pushOrder2Pas;
import static com.yungu.swift.order.model.enums.OrderErrorEnum.GRAB_ERROR_1001;
import static com.yungu.swift.order.model.enums.OrderErrorEnum.GRAB_ERROR_1003;
import static java.time.temporal.ChronoUnit.DAYS;

/**
 * 派单接口
 *
 * @author cuixiuyin
 * @date 2017/12/26
 */
@Slf4j
@Service
public class OrderAssignServiceImpl implements OrderAssignService {
    private static final int POOL_SIZE = Runtime.getRuntime().availableProcessors() + 1;
    private static final BigDecimal THOUSAND = new BigDecimal("1000");
    /**
     * 订单最大存活期为5分钟 = 300000毫秒
     **/
    private static final Integer ORDER_MAX_LIFETIME_MILLISECOND = 300000;
    public static final String ASSIGN_ORDER_LOCK = "assignOrderLock";
    private static final String ASSIGN_LOCK = "assignLock";

    private static final ScheduledExecutorService assignScheduleService = new ScheduledThreadPoolExecutor(POOL_SIZE,
            new BasicThreadFactory.Builder().namingPattern("assign-order-schedule-pool").build());

    private static final ScheduledExecutorService grabScheduleService = new ScheduledThreadPoolExecutor(POOL_SIZE,
            new BasicThreadFactory.Builder().namingPattern("order-push-pool").build());

    public static final Map<String, ScheduledFuture> scheduledFuturePool = new ConcurrentHashMap<>(POOL_SIZE);
    private static final Map<String, OrderAssignScheduleTaskVo> scheduledTaskVoPool = new ConcurrentHashMap<>(POOL_SIZE);

    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private OrderEvaluateMapper orderEvaluateMapper;
    @Autowired
    private OrderDetailMapper orderDetailMapper;
    @Autowired
    private OrderFareMapper orderFareMapper;
    @Autowired
    private OrderService orderService;
    @Autowired
    private OrderJoinService orderJoinService;
    @Autowired
    private OrderDetailService orderDetailService;
    @Autowired
    private OrderFareService orderFareService;
    @Autowired
    private OrderRiskControlService orderRiskControlService;
    @Autowired
    private OrderOperateLogService orderOperateLogService;
    @Autowired
    private OrderSecretNoService orderSecretNoService;
    @Autowired
    private RedisCacheService redisCacheService;
    @Autowired
    private RedisStringCacheService redisStringCacheService;
    @Autowired
    private RedisLock redisLock;
    @Autowired
    private CrosstownOrderProcessor crosstownOrderProcessor;

    @Reference
    private SysAssignConfigService sysAssignConfigService;
    @Reference
    private SysWayService sysWayService;
    @Reference
    private SysBusinessCityService sysBusinessCityService;
    @Reference
    private LocationService locationService;
    @Reference
    private PushService pushService;
    @Reference
    private DriverService driverService;
    @Reference
    private CarService carService;
    @Reference
    private CarModelValuationService carModelValuationService;
    @Reference
    private PassengerService passengerService;
    @Reference
    private DriverStatusCycleService driverStatusCycleService;
    @Reference
    private DriverQueueService driverQueueService;
    @Reference
    private DistanceService distanceService;
    @Reference
    private SysBusinessOperateLogService sysBusinessOperateLogService;

    @Override
    public ResponseData<Boolean> assignRealTime(String orderUuid) {
        //锁订单
        if (!redisLock.uniqueLock(ASSIGN_ORDER_LOCK + orderUuid, 10000)) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "缓存锁判定订单派单正在进行中，请勿重复执行");
        }
        try {
            //先校验订单的接单司机和指派司机都未空才进行推单操作
            OrderDto orderDto = orderMapper.list(MapUtils.build("uuid", orderUuid)).get(0);
            if (StringUtils.isEmpty(orderDto.getActualDriverUuid()) && StringUtils.isEmpty(orderDto.getAssignDriverUuid())) {
                Map<String, Object> map = MapUtils.build("orderUuid", orderUuid);
                //获取订单信息详情
                OrderDetailDto orderDetailDto = orderDetailMapper.list(map).get(0);
                //获取订单费用详情
                OrderFareDto orderFareDto = orderFareMapper.list(map).get(0);
                //保留静态数据
                saveOrUpdateStaticDataOnOrderMatch(orderDto);
                //实时单派单逻辑，派单失败后会采取抢单方式
                if (OrderConstant.NEW_ORDER_TYPE_INTERACTIVE_PUSH == orderDto.getTypeInteractive()) {
                    log.info("开始派单,orderUuid:{}", orderUuid);
                    //获取配置的派单半径
                    Map<String, Object> paramsMap = MapUtils.build();
                    paramsMap.put("districtUuid", orderDetailDto.getOriginCityUuid());
                    paramsMap.put("businessType", orderDto.getTypeModule());
                    ResponseData<SysAssignConfigDto> responseWrapper = sysAssignConfigService.get(paramsMap);
                    if (!responseWrapper.isSuccess()) {
                        log.info("获取不到派单配置参数，districtUuid：{}，businessType：{}", orderDetailDto.getOriginCityUuid(),
                                orderDto.getTypeModule());
                        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "派单失败", Boolean.FALSE);
                    }
                    SysAssignConfigDto sysAssignConfigDto = responseWrapper.getData();
                    log.info("开始派单,orderUuid:{},---sysAssignConfigDto:---", orderUuid, JsonUtils.toJSONString(sysAssignConfigDto));
                    //设置派单配置
                    setTaskConfig(orderDto, orderDetailDto, orderFareDto, sysAssignConfigDto);
                    //添加定时派单线程
                    addScheduleTask(orderUuid);
                }
                // 预约单：直接推单
                if (OrderConstant.NEW_ORDER_TYPE_INTERACTIVE_SNATCH == orderDto.getTypeInteractive()) {
                    log.info("开始抢单");
                    pushNewOrderToDriver(orderDto, orderDetailDto, orderFareDto.getCarModelValuationUuid());
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            redisLock.unLock(ASSIGN_ORDER_LOCK + orderUuid);
        }
        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "订单派单异常");
    }

    /**
     * 设置派单配置
     */
    private void setTaskConfig(OrderDto orderDto, OrderDetailDto orderDetailDto, OrderFareDto orderFareDto,
                               SysAssignConfigDto sysAssignConfigDto) {
        String orderUuid = orderDto.getUuid();
        //设置定时任务线程相关参数
        OrderAssignScheduleTaskVo orderAssignScheduleTaskVo = new OrderAssignScheduleTaskVo();
        orderAssignScheduleTaskVo.setAppid(orderDto.getAppid());
        orderAssignScheduleTaskVo.setTaskId(orderUuid);
        orderAssignScheduleTaskVo.setFirstRadius(sysAssignConfigDto.getFirstRadius());
        orderAssignScheduleTaskVo.setIncreaseRadius(sysAssignConfigDto.getIncreaseRadius());
        orderAssignScheduleTaskVo.setMaxRadius(sysAssignConfigDto.getMaxRadius());
        orderAssignScheduleTaskVo.setIntervalSecond(sysAssignConfigDto.getIntervalSecond());
        orderAssignScheduleTaskVo.setMaxWaitSecond(sysAssignConfigDto.getMaxWaitSecond());
        orderAssignScheduleTaskVo.setListenDownTimestamp(System.currentTimeMillis() +
                sysAssignConfigDto.getListenDownSecond().multiply(THOUSAND).longValue());
        orderAssignScheduleTaskVo.setTaskStartTimeStamp(System.currentTimeMillis());
        orderAssignScheduleTaskVo.setInvokeCount(new AtomicInteger(0));
        orderAssignScheduleTaskVo.setPavementDistanceFlag(sysAssignConfigDto.getPavementDistanceFlag());
        orderAssignScheduleTaskVo.setDriverPreviousOrderFlag(sysAssignConfigDto.getDriverPreviousOrderFlag());
        orderAssignScheduleTaskVo.setDriverScoreFlag(sysAssignConfigDto.getDriverScoreFlag());
        orderAssignScheduleTaskVo.setCurrentDayOrderCountFlag(sysAssignConfigDto.getCurrentDayOrderCountFlag());

        //设置业务查询参数
        Map<String, Object> searchParams = new HashMap<>(16);
        searchParams.put("longitude", orderDetailDto.getOriginLng());
        searchParams.put("latitude", orderDetailDto.getOriginLat());
        searchParams.put("carModelValuationUuid", orderFareDto.getCarModelValuationUuid());
        searchParams.put("orderDto", orderDto);
        searchParams.put("orderDetailDto", orderDetailDto);
        searchParams.put("orderUuid", orderDto.getUuid());
        searchParams.put("newDriverPassengerMatch", sysAssignConfigDto.getNewDriverPassengerMatch());

        //如果进入火车站围栏 需要筛选司机选择接火车站订单
        if (OrderHelper.isStationOrder(orderDetailDto)) {
            searchParams.put("isStationOrder", 1);
        }

        orderAssignScheduleTaskVo.setSearchParams(searchParams);

        //配置加入池
        scheduledTaskVoPool.put(orderUuid, orderAssignScheduleTaskVo);
    }

    /**
     * 添加一个新的定时任务线程
     */
    private void addScheduleTask(final String orderUuid) {
        log.info("添加定时派单线程-订单[" + orderUuid + "]");
        final OrderAssignScheduleTaskVo orderAssignScheduleTaskVo = scheduledTaskVoPool.get(orderUuid);
        final ScheduledFuture scheduledFuture = assignScheduleService.scheduleAtFixedRate(() -> {
            //捕获异常防止发生异常后线程停止定时任务线程
            try {
                //超时停止线程
                if (isOvertime(orderAssignScheduleTaskVo)) {
                    log.info("定时派单线程-结束线程-原因[超时取消]-订单[" + orderUuid + "]");
                    //取消订单
                    String cancelReason = "超时取消-执行次数[" + orderAssignScheduleTaskVo.getInvokeCount() + "]-执行耗时[" + getInvokeDuration(orderAssignScheduleTaskVo) + "]秒";
                    invokeCancelOrder(orderAssignScheduleTaskVo, cancelReason);
                    cancelScheduleTask(orderAssignScheduleTaskVo.getTaskId());
                    return;
                }
                // 超过最大轮询半径停止线程
                if (isOverDistance(orderAssignScheduleTaskVo)) {
                    log.info("定时派单线程-结束线程-原因[超过最大轮询半径停止线程]-订单[" + orderUuid + "]");
                    //取消订单
                    String cancelReason = "范围内无司机-执行次数[" + orderAssignScheduleTaskVo.getInvokeCount() + "]-最大范围[" + orderAssignScheduleTaskVo.getMaxRadius() + "]公里";
                    invokeCancelOrder(orderAssignScheduleTaskVo, cancelReason);
                    cancelScheduleTask(orderAssignScheduleTaskVo.getTaskId());
                    return;
                }
                //订单状态不合法停止定时任务线程
                if (!isValid(orderUuid)) {
                    log.info("定时派单线程-结束线程-原因[订单状态改变]-订单[" + orderUuid + "]");
                    cancelScheduleTask(orderAssignScheduleTaskVo.getTaskId());
                    return;
                }
                //执行派单
                invokeAssignOrder(orderAssignScheduleTaskVo);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }, 0L, orderAssignScheduleTaskVo.getIntervalSecond().longValue(), TimeUnit.SECONDS);
        //定时任务线程加入线程控制池
        scheduledFuturePool.put(orderAssignScheduleTaskVo.getTaskId(), scheduledFuture);
    }

    /**
     * 派单方法
     *
     * @param scheduleTaskVo 配置对象
     */
    private void invokeAssignOrder(OrderAssignScheduleTaskVo scheduleTaskVo) {
        String driverUuid;
        try {
            String orderUuid = scheduleTaskVo.getTaskId();
            //执行次数+1
            int invokeCount = scheduleTaskVo.getInvokeCount().getAndIncrement();
            log.info("定时派单线程-执行派单-订单[" + orderUuid + "]-派单时间[" + DateUtils.format(new Date()) + "]" +
                    "-执行次数[" + scheduleTaskVo.getInvokeCount() + "]-执行耗时[" + getInvokeDuration(scheduleTaskVo) + "]秒");
            //获取范围内司机
            Map<String, Object> searchParams = scheduleTaskVo.getSearchParams();
            int maxDistance = scheduleTaskVo.getFirstRadius().intValue() + invokeCount * scheduleTaskVo.getIncreaseRadius().intValue();
            searchParams.put("maxDistance", maxDistance);
            ResponseData<List<DriverPoint>> scopeDriver = locationService.getScopeDriver(searchParams);
            if (!scopeDriver.isSuccess() || CollectionUtils.isEmpty(scopeDriver.getData())) {
                log.info("-----范围内无任何司机, orderUuid:{}--", orderUuid);
                return;
            }
            List<DriverPoint> scopeDriverData = scopeDriver.getData();
            //获取符合业务条件的司机（是否开始向下听单）
            if (System.currentTimeMillis() > scheduleTaskVo.getListenDownTimestamp()) {
                log.info("-----orderUuid:{},开始向下听单", orderUuid);
                searchParams.put("beginListenDown", 1);
            }
            List<DriverPoint> filterDriver = filterDriver(scopeDriverData, searchParams);
            if (CollectionUtils.isEmpty(filterDriver)) {
                log.info("-----无符合业务司机, orderUuid:{},", orderUuid);
                return;
            }
            //处理顺路模式司机
            handleSameWayDriver(filterDriver, (OrderDto) scheduleTaskVo.getSearchParams().get("orderDto"),
                    (OrderDetailDto) scheduleTaskVo.getSearchParams().get("orderDetailDto"));

            // 按距离排序，取业务司机前 100 个
            filterDriver = filterDriver.stream().parallel().sorted(Comparator.comparingDouble(DriverPoint::getDistance))
                    .limit(100).collect(Collectors.toList());
            log.info("订单：{} 符合业务司机:{}", orderUuid, JsonUtils.toJSONString(filterDriver));
            // 是否开启路面距离过滤
            if (scheduleTaskVo.getPavementDistanceFlag() == 1) {
                log.info("开始路面距离计算, orderUuid:{},", orderUuid);
                Map<String, Object> taskVoSearchParams = scheduleTaskVo.getSearchParams();
                ResponseData<CarModelValuationDto> responseData = carModelValuationService.get(String.valueOf(
                        taskVoSearchParams.get("carModelValuationUuid")));
                if (!responseData.isSuccess() || responseData.getData() == null) {
                    log.info("-----获取不到计价规则, carModelValuationUuid:{}--", taskVoSearchParams.get("carModelValuationUuid"));
                    return;
                }
                // 判断当前是否是高峰期(考虑跨天) 路面距离 高峰期取 3/4 ，平常取 1/2
                int distance = getPavementDistance(responseData.getData(), maxDistance);
                // 调用高德里面距离计算
                String destination = taskVoSearchParams.get("longitude") + "," + taskVoSearchParams.get("latitude");
                String origins = filterDriver.stream().map(driverPoint -> driverPoint.getCoordinate().getLng() + ","
                        + driverPoint.getCoordinate().getLat()).collect(Collectors.joining("|"));
                // 做降级处理，非强制依赖路面距离计算
                try {
                    ResponseData<List<DistanceVo>> getDistance = distanceService.getDistance(origins, destination);
                    if (getDistance.isSuccess() && CollectionUtils.isNotEmpty(getDistance.getData())) {
                        List<DistanceVo> distanceVos = getDistance.getData();
                        log.info("订单：{} 路面距离计算结算：{}", orderUuid, JsonUtils.toJSONString(distanceVos));
                        //过滤点
                        ListIterator<DriverPoint> iterator = filterDriver.listIterator();
                        while (iterator.hasNext()) {
                            int index = iterator.nextIndex();
                            Integer pavementDistance = distanceVos.get(index).getDistance();
                            if (pavementDistance > distance) {
                                iterator.remove();
                                continue;
                            }
                            DriverPoint driverPoint = iterator.next();
                            driverPoint.setDistance(pavementDistance.doubleValue());
                        }
                    }
                } catch (Exception e) {
                    log.error("路面距离调用异常，orderUuid:{}--", orderUuid, e);
                }
            }
            if (CollectionUtils.isEmpty(filterDriver)) {
                log.info("路面距离过滤掉所有的司机，orderUuid:{}--", orderUuid);
                return;
            }
            log.info("路面距离过滤后的结果：{}，orderUuid:{}--", JsonUtils.toJSONString(filterDriver), orderUuid);
            // 计算司机分数
            log.info("开始计算司机距离下单点分值，orderUuid:{}--", orderUuid);
            AssignScoreHandler driverDistanceHandler = new DriverDistanceHandler(maxDistance, filterDriver);
            AssignScoreHandler driverPreviousOrderHandler = new EmptyHandler();
            AssignScoreHandler driverScoreHandler = new EmptyHandler();
            AssignScoreHandler currentDayOrderCount = new EmptyHandler();
            if (scheduleTaskVo.getDriverPreviousOrderFlag() == 1) {
                log.info("司机距离前一单订单完成分数统计，orderUuid:{}--", orderUuid);
                driverPreviousOrderHandler = new DriverPreviousOrderHandler(orderMapper);
            }
            if (scheduleTaskVo.getDriverScoreFlag() == 1) {
                log.info("司机评分分数统计，orderUuid:{}--", orderUuid);
                driverScoreHandler = new DriverScoreHandler(orderEvaluateMapper);
            }
            if (scheduleTaskVo.getCurrentDayOrderCountFlag() == 1) {
                log.info("司机当天订单量分数统计，orderUuid:{}--", orderUuid);
                currentDayOrderCount = new CurrentDayOrderCountHandler(orderMapper);
            }
            // 组织责任链
            driverDistanceHandler.setNextHandler(driverPreviousOrderHandler);
            driverPreviousOrderHandler.setNextHandler(driverScoreHandler);
            driverScoreHandler.setNextHandler(currentDayOrderCount);
            List<AssignScoreParam> scoreParams = filterDriver.stream().map(driverPoint -> {
                AssignScoreParam scoreParam = new AssignScoreParam();
                scoreParam.setDriverUuid(driverPoint.getDriverUuid());
                return scoreParam;
            }).collect(Collectors.toList());
            driverDistanceHandler.calculation(scoreParams);

            log.info("orderUuid：{}，司机计算分数结果：{}", orderUuid, JsonUtils.toJSONString(scoreParams));

            //司机加锁
            log.info("-----orderUuid:{},开始选举最优司机-业务符合司机数量[{}]", orderUuid, filterDriver.size());
            String optimumDriverUuid = getOptimumDriverUuid(scoreParams, scheduleTaskVo.getMaxWaitSecond().multiply(THOUSAND).longValue());
            if (optimumDriverUuid == null) {
                ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到符合条件的司机-锁");
            }
            //得到最优司机
            driverUuid = optimumDriverUuid;
            log.info("-----orderUuid:{},获取最优司机成功:{}", orderUuid, driverUuid);

            //查询司机信息
            DriverDto driverDto = driverService.get(driverUuid).getData();
            if (driverDto == null) {
                return;
            }
            // 派单结束后处理业务逻辑
            handleOnAssignDriverSuccess(Lists.newArrayList(driverUuid), driverDto, (OrderDto) searchParams.get("orderDto"),
                    (OrderDetailDto) searchParams.get("orderDetailDto"), String.valueOf(searchParams.get("carModelValuationUuid")));

        } catch (Exception e) {
            log.error("派单异常，orderUuid:{}", scheduleTaskVo.getTaskId(), e);
        }
    }

    /**
     * 处理顺路模式
     */
    private List<DriverPoint> handleSameWayDriver(List<DriverPoint> filterDriver, OrderDto orderDto, OrderDetailDto orderDetailDto) {
        List<String> driverUuids = filterDriver.stream().map(DriverPoint::getDriverUuid).collect(Collectors.toList());
        ResponseData<List<DriverSameWayInfoVo>> sameWayInfoRsd = driverService.getSameWayDriverUuid(orderDto.getTypeModule(), driverUuids);
        if (sameWayInfoRsd.isSuccess() && CollectionUtils.isNotEmpty(sameWayInfoRsd.getData())) {
            List<DriverSameWayInfoVo> removeList = sameWayInfoRsd.getData();
            //开启顺路模式与订单不满足距离条件的司机
            DriverConfig.OrderBean.RemindTypeBean remindTypeBean = ApplicationConfig.DRIVER_CONFIG.getOrder().getRemindType();
            Double sameWayDistance = 0d;
            switch (orderDto.getTypeModule()) {
                case 1:
                    sameWayDistance = remindTypeBean.getTaxi().getSameWayDistance();
                    break;
                case 2:
                    sameWayDistance = remindTypeBean.getSpecial().getSameWayDistance();
                    break;
                case 4:
                    sameWayDistance = remindTypeBean.getExpress().getSameWayDistance();
                    break;
                default:
                    break;
            }
            sameWayDistance = ParamUtil.defaultIfNull(sameWayDistance, 0d);
            Iterator<DriverSameWayInfoVo> it = removeList.iterator();
            while (it.hasNext()) {
                DriverSameWayInfoVo sameWayVo = it.next();
                Double actualDistance = LocationUtils.getLineDistance(orderDetailDto.getDestLng(), orderDetailDto.getDestLat(), sameWayVo.getSameWayLng(), sameWayVo.getSameWayLat()) / 1000;
                if (actualDistance <= sameWayDistance) {
                    log.info("订单{},司机{}满足顺路模式，实际距离{},顺路设置距离{}", orderDto.getUuid(), sameWayVo.getDriverUuid(), actualDistance, sameWayDistance);
                    it.remove();
                }
            }
            if (CollectionUtils.isNotEmpty(removeList)) {
                log.info("订单{}，顺路距离{}，司机{}不满足条件", orderDto.getUuid(), sameWayDistance, JsonUtils.toJSONString(removeList));
                final Map<String, DriverSameWayInfoVo> map = removeList.stream().collect(Collectors.toMap(DriverSameWayInfoVo::getDriverUuid, Function.identity()));
                filterDriver.removeIf(driverPoint -> map.containsKey(driverPoint.getDriverUuid()));
            }
        }
        return filterDriver;
    }

    /**
     * 获得路面过滤距离
     *
     * @param carModelsLevelDto
     * @param maxDistance
     * @return
     */
    private int getPavementDistance(CarModelValuationDto carModelsLevelDto, int maxDistance) {
        Instant oneStart = carModelsLevelDto.getPremiumOneStart().toInstant();
        Instant oneEnd = carModelsLevelDto.getPremiumOneEnd().toInstant();
        if (oneEnd.isBefore(oneStart)) {
            oneEnd = oneEnd.plus(1, DAYS);
        }
        Instant twoStart = carModelsLevelDto.getPremiumTwoStart().toInstant();
        Instant twoEnd = carModelsLevelDto.getPremiumTwoEnd().toInstant();
        if (twoEnd.isBefore(twoStart)) {
            twoEnd = twoEnd.plus(1, DAYS);
        }
        Instant now = Instant.now();
        // 单位：米
        Integer distance = maxDistance * 1000 / 2;
        if (now.isAfter(oneStart) && now.isBefore(oneEnd)) {
            distance = maxDistance * 1000 * 3 / 4;
        }
        if (now.isAfter(twoStart) && now.isBefore(twoEnd)) {
            distance = maxDistance * 1000 * 3 / 4;
        }
        return distance;
    }

    /**
     * 对距离范围的司机进行业务过滤
     * 过滤包括：1.在职，2.出车，3听单状态，4.车型，5.座位数，6.已接单状态，7.范围内司机，8.非已锁司机
     *
     * @param scopeDriverData 范围内司机uuid集合
     * @param map             业务参数
     */
    private List<DriverPoint> filterDriver(List<DriverPoint> scopeDriverData, Map<String, Object> map) {
        map.put("orderUuid", map.get("orderUuid"));
        // mongoDB 司机列表
        List<String> driverUuids = scopeDriverData.stream().map(DriverPoint::getDriverUuid).collect(
                Collectors.toList());
        map.put("uniqueSortedDriverUuidList", driverUuids);
        // 排除被锁定的司机
        Object object = redisCacheService.get(ASSIGN_DRIVER_LOCK);
        if (object != null) {
            map.put("lockedDriverUuidList", object);
        }
        log.info("订单:{} 查找符合业务司机参数 {}", map.get("orderUuid"), JsonUtils.toJSONString(map));
        ResponseData<List<String>> responseData = driverService.filterAssignDriver(map);
        if (responseData.isSuccess() && CollectionUtils.isNotEmpty(responseData.getData())) {
            List<String> assignUuids = responseData.getData();
            log.info("orderUuid:{}, 业务司机列表：{}", map.get("orderUuid"), JsonUtils.toJSONString(assignUuids));
            return scopeDriverData.stream().parallel().filter(driverPoint -> assignUuids.contains(driverPoint.getDriverUuid()))
                    .collect(Collectors.toList());
        }
        return Lists.newArrayList();
    }

    /**
     * 获取最优司机
     *
     * @param filterDriver
     * @param timeout      锁订单超时时间
     * @return String
     */
    private String getOptimumDriverUuid(List<AssignScoreParam> filterDriver, long timeout) {
        try {
            if (redisLock.lock(ASSIGN_LOCK, timeout)) {
                // 得到锁后，锁定司机
                List<String> lockedDriverList = new ArrayList<>();
                Object object = redisCacheService.get(ASSIGN_DRIVER_LOCK);
                if (object != null) {
                    lockedDriverList = (List<String>) object;
                }
                // 选举最优司机 1. 司机分数排序 2. 没有被锁定
                filterDriver.sort(Comparator.comparingDouble(AssignScoreParam::getScore).reversed());
                Iterator<AssignScoreParam> it = filterDriver.iterator();
                while (it.hasNext()) {
                    AssignScoreParam scoreParam = it.next();
                    if (lockedDriverList.contains(scoreParam.getDriverUuid())) {
                        continue;
                    }
                    lockedDriverList.add(scoreParam.getDriverUuid());
                    redisCacheService.set(ASSIGN_DRIVER_LOCK, lockedDriverList);
                    return scoreParam.getDriverUuid();
                }
            }
        } catch (InterruptedException e) {
            log.error("OrderAssignServiceImpl getOptimumDriverUuid Thread.sleep InterruptedException.", e);
        } finally {
            redisLock.unLock(ASSIGN_LOCK);
        }
        return null;
    }

    /**
     * 执行超时/无范围 取消订单业务逻辑
     *
     * @param orderAssignScheduleTaskBean 配置对象
     */
    private void invokeCancelOrder(OrderAssignScheduleTaskVo orderAssignScheduleTaskBean, String cancelReason) {
        Map<String, Object> searchParams = orderAssignScheduleTaskBean.getSearchParams();
        OrderDto orderDto = (OrderDto) searchParams.get("orderDto");
        OrderDetailDto orderDetailDto = (OrderDetailDto) searchParams.get("orderDetailDto");
        log.info("派单失败，原因:{}，执行抢单,orderUuid:{}", cancelReason, orderDto.getUuid());
        orderDto.setTypeInteractive(OrderConstant.NEW_ORDER_TYPE_INTERACTIVE_SNATCH);
        OrderDto updateOrderDto = new OrderDto();
        updateOrderDto.setTypeInteractive(OrderConstant.NEW_ORDER_TYPE_INTERACTIVE_SNATCH);
        updateOrderDto.setUuid(orderDto.getUuid());
        int affectedRowCount = orderMapper.edit(updateOrderDto);
        if (affectedRowCount > 0) {
            pushNewOrderToDriver(orderDto, orderDetailDto, String.valueOf(searchParams.get("carModelValuationUuid")));

        }
    }

    /**
     * 关闭指定任务id的定时任务线程
     *
     * @param taskId 任务id
     */
    private void cancelScheduleTask(String taskId) {
        ScheduledFuture scheduledFuture = scheduledFuturePool.get(taskId);
        if (scheduledFuture == null) {
            return;
        }
        scheduledFuture.cancel(true);
        //移出控制池
        scheduledFuturePool.remove(taskId);
        scheduledTaskVoPool.remove(taskId);
    }

    /**
     * 判断是否超时
     *
     * @param orderAssignScheduleTaskVo 配置对象
     * @return boolean 是否超时
     */
    private boolean isOvertime(OrderAssignScheduleTaskVo orderAssignScheduleTaskVo) {
        return System.currentTimeMillis() > orderAssignScheduleTaskVo.getTaskStartTimeStamp() + orderAssignScheduleTaskVo
                .getMaxWaitSecond().multiply(THOUSAND).longValue();
    }

    /**
     * 判断是否超过最大轮询半径
     *
     * @param orderAssignScheduleTaskVo
     * @return
     */
    private Boolean isOverDistance(OrderAssignScheduleTaskVo orderAssignScheduleTaskVo) {
        int distance = orderAssignScheduleTaskVo.getFirstRadius().intValue() + orderAssignScheduleTaskVo.getInvokeCount()
                .get() * orderAssignScheduleTaskVo.getIncreaseRadius().intValue();
        return distance > orderAssignScheduleTaskVo.getMaxRadius().intValue();
    }

    /**
     * 判断是否是有效可派单的订单
     *
     * @param orderUuid 订单uuid
     * @return boolean 是否有效
     */
    private boolean isValid(String orderUuid) {
        OrderDto orderDto = orderMapper.list(MapUtils.build("uuid", orderUuid)).get(0);
        return OrderConstant.ORDER_MAIN_STATUS_INITIAL.equals(orderDto.getMainStatus()) && OrderConstant.ORDER_STATUS_WAIT
                .equals(orderDto.getSubStatus());
    }

    /**
     * 获取已执行的时长
     *
     * @param orderAssignScheduleTaskVo 配置对象
     * @return Long 时长
     */
    private Long getInvokeDuration(OrderAssignScheduleTaskVo orderAssignScheduleTaskVo) {
        return (System.currentTimeMillis() - orderAssignScheduleTaskVo.getTaskStartTimeStamp()) / 1000;
    }


    @Override
    public ResponseData<JsonOrderDetailVo> updGrab(String orderUuid, DriverDto driverDto, String uploadText) {
        if (!redisLock.uniqueLock("updGrab" + orderUuid, 60000)) {
            return ResponseData.buildErrorResponse(GRAB_ERROR_1001.getCode(), GRAB_ERROR_1001.getMsg());
        }
        try {
            //根据orderUuid查询该订单，没有返回null
            OrderDto orderDto = orderService.get(orderUuid).getData();
            if (null == orderDto) {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "检索不到订单");
            }
            //根据orderUuid查询该订单，没有返回null
            List<OrderDetailDto> detailDtoList = orderDetailService.list(MapUtils.build("orderUuid", orderUuid)).getData();
            if (CollectionUtils.isEmpty(detailDtoList)) {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "检索不到订单详情");
            }
            OrderDetailDto orderDetailDto = detailDtoList.get(0);
            //司机抢单校验进行中即时单或者相同时段预约单
            ResponseData<Boolean> driverOrderStatus = orderRiskControlService.driverHasGoingOrder(driverDto.getUuid(), orderDetailDto.getDeparTime());
            if (!driverOrderStatus.isSuccess()) {
                return ResponseData.buildErrorResponse(driverOrderStatus.getErrCode(), driverOrderStatus.getMsg());
            }
            CarDto carDto = carService.get(driverDto.getCarUuid()).getData();
            if (carDto == null) {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到车辆信息");
            }
            // 订单状态检查
            ResponseData<Void> statusCheck = OrderAssignHelper.grabOrderStatusCheck(orderDto.getMainStatus(), orderDto.getSubStatus());
            if (!statusCheck.isSuccess()) {
                return ResponseData.buildErrorResponse(statusCheck.getErrCode(), statusCheck.getMsg());
            }
            // 等待接驾状态 ，如果超过五分钟则取消订单
            if ((System.currentTimeMillis() - orderDto.getCreateOn().getTime()) > ORDER_MAX_LIFETIME_MILLISECOND) {
                orderService.updateOrderStatus(orderDto, OrderConstant.ORDER_STATUS_NO_ANSWER, OrderConstant.ORDER_MAIN_STATUS_CANCEL);
                return ResponseData.buildErrorResponse(GRAB_ERROR_1003.getCode(), GRAB_ERROR_1003.getMsg());
            }
            //更新订单主表
            OrderDto orderParam = new OrderDto();
            orderParam.setUuid(orderUuid);
            orderParam.setMainStatus(OrderConstant.ORDER_MAIN_STATUS_DOING);
            // 即时订单，去接乘客；预约订单，行程确定
            orderParam.setSubStatus(CommonConstant.TYPE_TIME_REAL_TIME == orderDto.getTypeTime() ?
                    OrderConstant.ORDER_STATUS_GO : OrderConstant.ORDER_STATUS_CONFIRM);
            orderParam.setActualDriverUuid(driverDto.getUuid());
            orderParam.setCarUuid(driverDto.getCarUuid());
            orderParam.setUpdateOn(new Date());
            orderParam.setDistributeTime(new Date());
            orderMapper.edit(orderParam);

            //新增orderFare 记录,有存在记录则更改
            OrderFareDto orderFareParam = new OrderFareDto();
            //司机接单时间
            orderFareParam.setDriReceiveTime(new Date());
            OrderFareDto orderFareDto = orderFareService.get(MapUtils.build("orderUuid", orderUuid)).getData();
            if (orderDetailDto != null) {
                orderFareParam.setUuid(orderFareDto.getUuid());
                orderFareParam.setCarModelValuationUuid(orderFareDto.getCarModelValuationUuid());
            }
            //实时订单，设置出发时间
            if (orderDto.getTypeTime() == CommonConstant.TYPE_TIME_REAL_TIME) {
                orderFareParam.setDriDepartTime(new Date());
            }
            orderFareService.saveOrUpdate(orderFareDto);
            ResponseData<JsonOrderDetailVo> getOrderDetail = orderService.getOrderDetail(orderUuid, null);
            if (!getOrderDetail.isSuccess()) {
                return ResponseData.buildErrorResponse(getOrderDetail.getErrCode(), getOrderDetail.getMsg());
            }
            JsonOrderDetailVo jsonOrderDetailVo = getOrderDetail.getData();
            //司机已抢单，推送给乘客
            pushOrder2Pas(orderDto.getPassengerUuid(), orderDto.getUuid(), orderDto.getAppid(), "订单已被接，请耐心等待接驾",
                    "司机已接单", PushContent.ORDER_DRIVER_RUSH_ORDER_SUCCESS, MapUtils.build("typeModule", orderDto.getTypeModule()));
            //增加司机的累计接单数
            DriverDto driverParam = new DriverDto();
            driverParam.setOrderCount(driverDto.getOrderCount() == null ? 1 : driverDto.getOrderCount() + 1);
            driverParam.setUuid(driverDto.getUuid());
            CompletableFuture.runAsync(() -> driverService.edit(driverParam));
            //给其余司机推送消息
            List<String> userUuids = (List<String>) redisCacheService.get("push" + orderUuid);
            if (userUuids != null) {
                userUuids.remove(driverDto.getUuid());
                pushListOrder2Dri(userUuids, orderDto.getUuid(), orderDto.getAppid(), null, "订单已被其他司机抢走",
                        PushContent.ORDER_DRIVER_RUSH_ORDER_GRAB);
            }
            if (ApplicationConfig.COMMON_CONFIG.getPrivacyNumber()) {
                //新增隐私绑定
                log.info("开始隐私号绑定，orderUuid:{}", orderUuid);
                SecretNoParam secretNoParam = new SecretNoParam();
                secretNoParam.setOrderUuid(orderDto.getUuid());
                secretNoParam.setPassengerMobile(orderDetailDto.getActualPasMob());
                secretNoParam.setDriverMobile(driverDto.getMobile());
                orderSecretNoService.addBingding(secretNoParam);
            }
            uploadTextResult(uploadText);
            //查询最新的订单信息
            OrderDto orderDtoNew = orderService.get(orderUuid).getData();
            // 因为与主逻辑无关 所以异步统计里程(司机抢单分为实时单和预约单，实施单直接记录空驶里程，预约单等后续司机出发去接乘客时记录空驶里程)
            if (CommonConstant.TYPE_TIME_REAL_TIME == orderDtoNew.getTypeTime()) {
                ThreadExecutorUtils.execute(new DriverStatusCycleRunnable(driverStatusCycleService, locationService,
                        orderDtoNew.getAppid(), orderDtoNew.getActualDriverUuid(), orderDtoNew.getUuid(),
                        // 空驶
                        orderDtoNew.getCarUuid(), DriverStatusCycleDto.ACTION_LEAVE));
            }
            //静态数据保存
            CompletableFuture.runAsync(() -> saveOrUpdateStaticDataOnOrderMatch(orderParam));
            //实时单抢单发短信给紧急联系人
            if (orderDtoNew.getTypeTime() == 1) {
                CompletableFuture.runAsync(() -> OrderPushHelper.passengerEmergencyPush(orderDto, orderDetailDto, driverDto, carDto));
            }
            return ResponseData.buildSuccessResponse("抢单成功", jsonOrderDetailVo);
        } catch (Exception e) {
            log.error("OrderAssignServiceImpl updGrab error.orderUuid:{}", orderUuid, e);
        } finally {
            redisCacheService.delete("updGrab" + orderUuid);
        }
        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "抢单失败");
    }

    @Override
    public ResponseData<Boolean> reassign(AdminAssOrCloseParam assOrCloseParam) {
        //检索订单信息
        OrderDto order = this.orderMapper.list(MapUtils.build("uuid", assOrCloseParam.getOrderUuid())).get(0);
        if (order == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "检索不到订单");
        }
        //检索计费规则
        OrderFareDto orderFareDto = orderFareService.findByOrderUuid(assOrCloseParam.getOrderUuid()).getData();
        if (orderFareDto == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "检索不到计费规则");
        }
        String carModelValuationUuid = orderFareDto.getCarModelValuationUuid();
        //判断订单状态是否正常
        if (order.getSubStatus().intValue() == OrderConstant.ORDER_STATUS_WAIT.intValue()) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "改派订单失败，新行程不可以改派");
        }
        if (order.getSubStatus().intValue() != OrderConstant.ORDER_STATUS_CONFIRM.intValue()
                && order.getSubStatus().intValue() != OrderConstant.ORDER_STATUS_GO.intValue()) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "改派订单失败，行程开始前才可以改派");
        }
        //检索订单详情信息
        OrderDetailDto orderDet = orderDetailService.get(MapUtils.build("orderUuid", assOrCloseParam.getOrderUuid())).getData();
        if (orderDet == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "检索不到订单详情");
        }
        String oldDriverUuid = order.getActualDriverUuid();
        //检索乘客信息
        PassengerDto passenger = passengerService.get(order.getPassengerUuid()).getData();
        if (passenger == null) {
            passenger = new PassengerDto();
        }
        //检索司机信息
        Map<String, Object> build = MapUtils.build(4);
        build.put("mobile", assOrCloseParam.getAssMobile());
        build.put("appid", assOrCloseParam.getAppid());
        build.put("type", assOrCloseParam.getBusinessType());
        DriverVo assDriver = this.driverService.commonSelInfo(build).getData();
        if (assDriver == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "检索不到指定的司机，手机号：" + assOrCloseParam.getAssMobile());
        }
        //过滤司机
        List<String> driverIdList = Lists.newArrayList(assDriver.getUuid());
        ResponseData<List<String>> responseData;
        String originCityUuid = orderDet.getOriginCityUuid();
        //实时订单
        if (order.getTypeTime() == CommonConstant.TYPE_TIME_REAL_TIME) {
            //不限制自营/非自营
            responseData = driverService.filterGrabDriver(carModelValuationUuid, driverIdList, false, order.getSeatNum(),
                    originCityUuid, false);
        } else {
            //预约,日租,半日租
            responseData = driverService.filterGrabDriverReservation(carModelValuationUuid, driverIdList, orderDet
                    .getDeparTime(), null, order.getSeatNum(), orderDet.getOriginCityUuid(), false);
        }
        if (!responseData.isSuccess() || CollectionUtils.isEmpty(responseData.getData())) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "司机条件不匹配");
        }
        //修改订单信息
        OrderDto updOrder = new OrderDto();
        updOrder.setUuid(assOrCloseParam.getOrderUuid());
        updOrder.setAssignDriverUuid(assDriver.getUuid());
        updOrder.setActualDriverUuid(assDriver.getUuid());
        updOrder.setUpdateBy(assOrCloseParam.getUserUuid());
        updOrder.setUpdateOn(new Date());
        updOrder.setMatchTime(new Date());
        //改派后，直接指派司机，将交互类型调整为推单
        updOrder.setTypeInteractive(OrderConstant.NEW_ORDER_TYPE_INTERACTIVE_PUSH);
        orderMapper.edit(updOrder);

        //修改订单详情信息
        OrderDetailDto updOrderDet = new OrderDetailDto();
        updOrderDet.setUuid(orderDet.getUuid());
        updOrderDet.setUpdateBy(assOrCloseParam.getUserUuid());
        updOrderDet.setUpdateOn(new Date());
        orderDetailService.edit(updOrderDet);

        //通知消息
        InformThreadPoolUtil.execute(new OrderStatusInformThread(order, OrderEvent.CHANGE_ASSIGN_S));

        //改派司机时，更新隐私绑定
        String privacyMobile = updateSecretNoB(orderDet.getActualPasMob(), assDriver.getMobile(), updOrder.getUuid());
        privacyMobile = privacyMobile == null ? passenger.getMobile() : privacyMobile;
        //修改订单静态数据表
        saveOrUpdateStaticDataOnOrderMatch(updOrder);

        //插入订单生命周期表
        OrderOperateLogDto orderOperateLogDto = new OrderOperateLogDto();
        orderOperateLogDto.setUuid(StringUtils.buildUUID());
        orderOperateLogDto.setOrderUuid(order.getUuid());
        orderOperateLogDto.setAppid(order.getAppid());
        orderOperateLogDto.setType(OrderOperateLogDto.TYPE_ASS);
        orderOperateLogDto.setPreMainStatus(order.getMainStatus());
        orderOperateLogDto.setPreSubStatus(order.getSubStatus());
        orderOperateLogDto.setNowMainStatus(order.getMainStatus());
        orderOperateLogDto.setNowSubStatus(order.getSubStatus());
        orderOperateLogDto.setPreDriverUuid(oldDriverUuid);
        orderOperateLogDto.setNowDriverUuid(assDriver.getUuid());
        orderOperateLogDto.setReason(assOrCloseParam.getReason());
        orderOperateLogDto.setCreateBy(assOrCloseParam.getUserUuid());
        orderOperateLogDto.setCreateOn(new Date());
        CompletableFuture.runAsync(() -> orderOperateLogService.add(orderOperateLogDto));

        //更新静态数据
        CompletableFuture.runAsync(() -> saveOrUpdateStaticDataOnOrderMatch(order));

        //更新司机状态周期表
        //1、将原司机设为空驶
        ThreadExecutorUtils.execute(new DriverStatusCycleRunnable(
                driverStatusCycleService, locationService, assOrCloseParam.getAppid(), order.getActualDriverUuid(),
                "", order.getCarUuid(), 1
        ));
        //2、将新司机设为空载
        ThreadExecutorUtils.execute(new DriverStatusCycleRunnable(
                driverStatusCycleService, locationService, assOrCloseParam.getAppid(), assDriver.getUuid(),
                assOrCloseParam.getOrderUuid(), assDriver.getCarUuid(), 2
        ));
        try {
            // 1.推送给乘客
            String pasContent = "您的订单由于" + assOrCloseParam.getReason() + "的原因，由后台进行改派，改派司机："
                    + assDriver.getName() + "师傅，车辆" + assDriver.getPlateNum() + "，请及时和司机联系；";
            pushOrder2Pas(order.getPassengerUuid(), order.getUuid(), order.getAppid(), "订单被改派", pasContent,
                    PushContent.ORDER_DISTRIBUTE_TO_OTHER, MapUtils.build("typeModule", order.getTypeModule()));
            // 2.推送给原来的司机
            String oldDriContent = "您从" + orderDet.getOriginAddress() + "出发的订单已由后台改派成功";
            //实时订单
            if (order.getTypeTime() == CommonConstant.TYPE_TIME_REAL_TIME) {
                oldDriContent = "您从" + orderDet.getOriginAddress() + "到" + orderDet.getDestAddress() + "的订单已由后台改派成功";
            }
            Map<String, Object> extraMap = MapUtils.build();
            extraMap.put("report", "您有一个订单已被改派，可进入应用查看详情");
            extraMap.put("typeModule", order.getTypeModule());
            pushOrder2Dri(oldDriverUuid, order.getUuid(), order.getAppid(), "订单被改派", oldDriContent,
                    PushContent.ORDER_DISTRIBUTE_TO_OTHER, extraMap);
            // 3.推送给新司机
            String driMsg = "您收到" + CommonUtils.getTimeTodayOrTomorrow(orderDet.getDeparTime()) + "从" + orderDet.getOriginAddress() +
                    "出发的派单，联系电话" + privacyMobile == null ? passenger.getMobile() : privacyMobile +
                    "，请准时接驾；详询：" + ApplicationConfig.COMMON_CONFIG.getServiceTel();
            extraMap.put("report", "您收到一个新的派单，请及时联系乘客");
            pushOrder2Dri(assDriver.getUuid(), order.getUuid(), order.getAppid(), "订单被改派", driMsg,
                    PushContent.ORDER_CHANGE_DISTRIBUTE, extraMap);
            //4. 发送短信给乘客
            SendMessageUtils.assBeforeSend(passenger, assDriver, orderDet, orderDet.getDeparTime(), privacyMobile == null
                    ? passenger.getMobile() : privacyMobile);
            return ResponseData.buildSuccessResponse("订单改派成功", Boolean.TRUE);
        } catch (Exception e) {
            log.error("订单改派失败，orderUuid：{}", assOrCloseParam.getOrderUuid(), e);
            return ResponseData.buildSuccessResponse("订单改派失败", Boolean.FALSE);
        }
    }

    /**
     * 更新隐私小号司机信息
     */
    private String updateSecretNoB(String passengerMobile, String driverMobile, String orderUuid) {
        SecretNoParam secretNoParam = new SecretNoParam();
        secretNoParam.setOrderUuid(orderUuid);
        secretNoParam.setPassengerMobile(passengerMobile);
        secretNoParam.setDriverMobile(driverMobile);
        return orderSecretNoService.updateNoB(secretNoParam).getData();
    }

    @Override
    public ResponseData<Boolean> reassignTaxiOrder(AdminAssOrCloseParam assOrCloseParam) {
        //获取订单
        OrderDto orderDto = findOrder(assOrCloseParam.getOrderUuid());
        if (orderDto == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取订单失败");
        }
        //获取订单详情
        OrderDetailDto orderDetailDto = findOrderDetail(assOrCloseParam.getOrderUuid());
        if (orderDetailDto == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取订单详情失败");
        }
        //检索司机
        Map<String, Object> params = MapUtils.build(4);
        params.put("mobile", assOrCloseParam.getAssMobile());
        params.put("appid", assOrCloseParam.getAppid());
        DriverDto assDriverDto = driverService.get(params).getData();
        if (assDriverDto == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取派单司机失败");
        }
        if (assDriverDto.getStatus() != DriverConstant.DRIVER_STATUS_NORMAL) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "司机状态有误");
        }
        try {
            //更新订单信息
            OrderDto orderParam = new OrderDto();
            orderParam.setUuid(orderDto.getUuid());
            orderParam.setActualDriverUuid(assDriverDto.getUuid());
            orderParam.setAssignDriverUuid(assDriverDto.getUuid());
            orderParam.setUpdateBy(assOrCloseParam.getUserUuid());
            orderParam.setUpdateOn(new Date());
            orderMapper.edit(orderParam);
            //推送给指派司机
            Map<String, Object> extraMap = MapUtils.build();
            extraMap.put("typeModule", orderDto.getTypeModule());
            pushOrder2Dri(orderDto.getActualDriverUuid(), orderDto.getUuid(), orderDto.getAppid(), "收到一个指派订单",
                    "收到一个指派订单，请及时查看", PushContent.ORDER_CHANGE_DISTRIBUTE, extraMap);
            //推送乘客
            pushOrder2Pas(orderDto.getPassengerUuid(), orderDto.getUuid(), orderDto.getAppid(), "订单被改派",
                    "订单被改派,请及时查看", PushContent.ORDER_DISTRIBUTE_TO_OTHER, extraMap);
            //推送给被改派的司机
            extraMap.put("report", "您有一个订单已被改派，可进入应用查看详情");
            pushOrder2Dri(orderDto.getActualDriverUuid(), orderDto.getUuid(), orderDto.getAppid(), "订单被改派", "订单被改派,请及时查看",
                    PushContent.ORDER_DISTRIBUTE_TO_OTHER, extraMap);
            CompletableFuture.runAsync(() -> {
                //修改静态数据
                saveOrUpdateStaticDataOnOrderMatch(orderParam);
                //发送短信给乘客
                SendMessageUtils.upAssTaxiOrderSend(passengerService, orderDto, orderDetailDto);
            });
            return ResponseData.buildSuccessResponse(Boolean.TRUE);
        } catch (Exception e) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "系统异常，指派订单失败");
        }

    }

    @Override
    public ResponseData<String> addTaxiOrder(OrderDto orderDto, OrderDetailDto orderDetailDto, OrderFareDto orderFareDto) {
        //如果订单主表保存成功
        if (orderMapper.add(orderDto) > 0) {
            //保存订单详情表
            orderDetailDto.setOrderUuid(orderDto.getUuid());
            orderDetailService.saveOrUpdate(orderDetailDto);
            //保存订单费用表
            orderFareDto.setOrderUuid(orderDto.getUuid());
            orderFareService.saveOrUpdate(orderFareDto);
            //推送新的订单给司机
            pushNewOrderToDriver(orderDto, orderDetailDto, orderFareDto.getCarModelValuationUuid());
            return ResponseData.buildSuccessResponse("保存成功", orderDto.getUuid());
        }
        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "保存失败");
    }

    @Override
    public synchronized ResponseData<JsonOrderDetailVo> doAssignJoinOrder(CrosstownAssignOrderParam crosstownAssignOrderParam) {
        //原订单ID
        String curOrderUuid = crosstownAssignOrderParam.getCurrentOrderUuid();
        //指派司机ID
        String targetDriverUuid = crosstownAssignOrderParam.getTargetDriverUuid();
        //主订单ID
        String targetMainOrderUuid = crosstownAssignOrderParam.getTargetMainOrderUuid();
        //获取跨城订单与线路等相关信息
        ResponseData<Boolean> assignInfoRsd = getCrosstownAssignInfo(crosstownAssignOrderParam);
        if (!assignInfoRsd.isSuccess()) {
            return ResponseData.buildErrorResponse(assignInfoRsd.getErrCode(), assignInfoRsd.getMsg());
        }
        //是否是改派
        boolean isChangeAssign = false;

        //校验司机待出发的订单 是否满足接单条件 判断满足时是否加入已有主单或者新增一个主单
        if (StringUtils.isEmpty(crosstownAssignOrderParam.getTargetMainOrderUuid())) {
            ResponseData<Void> waitingOrderVerifyRsd = assignWaitingOrderVerify(crosstownAssignOrderParam);
            if (!waitingOrderVerifyRsd.isSuccess()) {
                return ResponseData.buildErrorResponse(waitingOrderVerifyRsd.getErrCode(), waitingOrderVerifyRsd.getMsg());
            }
        }
        //获取原订单信息
        OrderDto curOrder = crosstownAssignOrderParam.getCurrentOrderDto();
        OrderDetailDto curOrderDetail = crosstownAssignOrderParam.getCurrentOrderDetailDto();
        OrderFareDto curOrderFare = crosstownAssignOrderParam.getCurrentOrderFareDto();
        OrderDto curMainOrder = crosstownAssignOrderParam.getCurrentMainOrderDto();
        SysWayDto systemWayDto = crosstownAssignOrderParam.getSysWayDto();
        /*-----------------------------------------派单处理---------------------------------------------*/
        //是否是小件订单
        boolean isParcelOrder = crosstownAssignOrderParam.getCurrentOrderDto().getTypeModule() == CommonConstant.BUSINESS_TYPE_PARCEL;

        //获取目标主订单信息
        OrderDto targeMainOrder = null;
        OrderDetailDto targeMainOrderDetail = null;
        OrderFareDto targeMainOrderFare = null;
        if (StringUtils.isNotEmpty(crosstownAssignOrderParam.getTargetMainOrderUuid())) {
            ResponseData<Boolean> getMainOrderRsd = setMainOrderInfo(crosstownAssignOrderParam);
            if (!getMainOrderRsd.isSuccess()) {
                return ResponseData.buildErrorResponse(getMainOrderRsd.getErrCode(), getMainOrderRsd.getMsg());
            }
            targeMainOrder = crosstownAssignOrderParam.getTargetMainOrderDto();
            targeMainOrderDetail = crosstownAssignOrderParam.getTargetMainOrderDetailDto();
            targeMainOrderFare = crosstownAssignOrderParam.getCurrentOrderFareDto();
            crosstownAssignOrderParam.setTargetParcelOrderNum(targeMainOrderDetail.getParcelOrderNum());
        }
        //进行指派业务校验
        ResponseData verifyResultRsd = assignBusinessVerify(crosstownAssignOrderParam);
        if (!verifyResultRsd.isSuccess()) {
            //获取失败
            return verifyResultRsd;
        }
        /**
         * 改派判断：改派处理
         */
        if (null != crosstownAssignOrderParam.getCurrentMainOrderDto()) {
            JoinOrderParam joinOrderParam = new JoinOrderParam();
            joinOrderParam.setOrderUuid(crosstownAssignOrderParam.getCurrentOrderUuid());
            joinOrderParam.setCloseType(Constants.ORDER_CANCEL_SUB_STATUS_ASSIGNED);
            joinOrderParam.setCloseReason("改派订单");
            if (isParcelOrder) {
                joinOrderParam.setTypeModule(CommonConstant.BUSINESS_TYPE_PARCEL);
            }
            ResponseData<Boolean> cancelRS = orderJoinService.closeJoinOrder(joinOrderParam);
            if (!cancelRS.isSuccess()) {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "改派失败：" + cancelRS.getMsg());
            }
            isChangeAssign = true;
        }

        //创建主订单（按订单指派则更新）
        ResponseData saveRsd = saveAssignCrosstownOrder(curOrder, curOrderDetail, curOrderFare, targeMainOrder, targeMainOrderDetail, targeMainOrderFare,
                systemWayDto, crosstownAssignOrderParam, null);
        if (!saveRsd.isSuccess()) {
            return saveRsd;
        }
        /*----------------订单相关信息更新结束--------------------*/

        //司机退出排队
        //退出服务范围包含某个点（位置坐标）的所有起点排队 —— 此处以乘客订单坐标为判断标准
        Coordinate coordinate = new Coordinate();
        coordinate.setLng(curOrderDetail.getOriginLng());
        coordinate.setLat(curOrderDetail.getOriginLat());
        driverQueueService.quit(targetDriverUuid, coordinate);

        CrosstownOrderParam crosstownOrderParam = new CrosstownOrderParam();
        crosstownOrderParam.setOrderUuid(curOrder.getUuid());
        if (null == curMainOrder) {
            //消息推送
            //司机：收到派单推送
            pushService.sendMessage(crosstownAssignOrderParam.getTargetDriverUuid(), PushContentUtils.crosstownAssignToDriver(crosstownAssignOrderParam));

            //乘客：派单成功通知
            pushService.sendMessage(curOrder.getPassengerUuid(), PushContentUtils.crosstownAssignToPassener(curOrder.getUuid(), curOrder.getTypeModule(), curOrder.getAppid()));

            crosstownOrderParam.setMainOrderUuid(crosstownAssignOrderParam.getTargetMainOrderUuid());
            crosstownOrderProcessor.pushOtherPassenger(crosstownOrderParam);
            //司机短信
            SendMessageUtils.generalSend(crosstownAssignOrderParam.getDriverMobile(), MessageContentUtils.joinAssignDriverMsg(curOrderDetail, isParcelOrder), curOrder.getAppid());
            //乘客短信
            SendMessageUtils.generalSend(isParcelOrder ? curOrderDetail.getSenderMobile() : curOrderDetail.getActualPasMob(), MessageContentUtils.joinAssignPassengerMsg(crosstownAssignOrderParam.getDriverMobile(), crosstownAssignOrderParam.getPlateNum(), isParcelOrder), curOrder.getAppid());
        } else {
            //消息推送
            //获取原司机信息
            DriverDto oldDriver = driverService.get(MapUtils.build("uuid", curMainOrder.getActualDriverUuid())).getData();
            if (oldDriver == null) {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取原司机信息失败");
            }
            //原司机：提示被改派
            pushService.sendMessage(oldDriver.getUuid(), PushContentUtils.crosstowChangeAssignToCurDriver(crosstownAssignOrderParam));
            SendMessageUtils.generalSend(oldDriver.getMobile(), MessageContentUtils.joinChangeAssignOldDriverPushMsg(curOrderDetail, isParcelOrder), curOrder.getAppid());

            //新司机：提示收到改派
            pushService.sendMessage(targetDriverUuid, PushContentUtils.crosstowChangeAssignToNewDriver(crosstownAssignOrderParam));
            SendMessageUtils.generalSend(crosstownAssignOrderParam.getDriverMobile(), MessageContentUtils.joinChangeAssignNewDriverPushMsg(curOrderDetail, isParcelOrder), curOrder.getAppid());

            //乘客：提示被改派
            pushService.sendMessage(curOrder.getPassengerUuid(), PushContentUtils.crosstowChangeAssignToCurDriver(crosstownAssignOrderParam));
            SendMessageUtils.msgChangeAssignedByJoinOrderPas(curOrderDetail, crosstownAssignOrderParam.getDriverMobile(), crosstownAssignOrderParam.getPlateNum(), curOrderDetail.getActualPasMob());

            //推送拼车订单更新
            crosstownOrderParam.setMainOrderUuid(curMainOrder.getUuid());
            crosstownOrderProcessor.pushOtherPassenger(crosstownOrderParam);

            crosstownOrderParam.setMainOrderUuid(targetMainOrderUuid);
            crosstownOrderProcessor.pushOtherPassenger(crosstownOrderParam);

            //插入订单生命周期表
            OrderOperateLogDto orderOperateLogDto = new OrderOperateLogDto();
            orderOperateLogDto.setUuid(StringUtils.buildUUID());
            orderOperateLogDto.setOrderUuid(curOrder.getUuid());
            orderOperateLogDto.setType(OrderOperateLogDto.TYPE_ASS);
            orderOperateLogDto.setPreMainStatus(curOrder.getMainStatus());
            orderOperateLogDto.setPreSubStatus(curOrder.getSubStatus());
            orderOperateLogDto.setNowMainStatus(curOrder.getMainStatus());
            orderOperateLogDto.setNowSubStatus(curOrder.getSubStatus());
            orderOperateLogDto.setPreDriverUuid(curMainOrder.getActualDriverUuid());
            orderOperateLogDto.setNowDriverUuid(curOrder.getActualDriverUuid());
            orderOperateLogDto.setCreateBy(crosstownAssignOrderParam.getUserUuid());
            orderOperateLogDto.setCreateOn(new Date());
            orderOperateLogService.add(orderOperateLogDto);
        }
        // 返回该子订单信息
        if (curMainOrder != null) {
            saveOrUpdateStaticDataOnOrderMatch(curMainOrder);
        }
        if (curOrder != null) {
            saveOrUpdateStaticDataOnOrderMatch(curOrder);
        }
        if (targeMainOrder != null) {
            saveOrUpdateStaticDataOnOrderMatch(targeMainOrder);
        }
        //改派时插入日志
        if (isChangeAssign) {
            OrderHandleThreadPoolUtil.execute(() -> addLog(crosstownAssignOrderParam));
        }
        return ResponseData.buildSuccessResponse("派单成功", null);
    }

    /**
     * 插入修改日志
     */
    private void addLog(CrosstownAssignOrderParam crosstownAssignOrderParam) {
        try {
            SysBusinessOperateLogDto operateLogDto = new SysBusinessOperateLogDto();
            operateLogDto.setBeforeValue(crosstownAssignOrderParam.getCurDriverUuid());
            operateLogDto.setAfterValue(crosstownAssignOrderParam.getTargetDriverUuid());
            operateLogDto.setOperationCode(SysBusinessOperateEnum.UDP_ORDER_DRIVER.getCode());
            operateLogDto.setOperationName(SysBusinessOperateEnum.UDP_ORDER_DRIVER.getName());
            operateLogDto.setOperationDescribe("客服操作订单改派");
            operateLogDto.setCreateBy(crosstownAssignOrderParam.getUserUuid());
            operateLogDto.setCreateOn(new Date());
            operateLogDto.setAgentUuid(crosstownAssignOrderParam.getUserAgentUuid());
            operateLogDto.setCompanyUuid(crosstownAssignOrderParam.getUserCompanyUuid());
            operateLogDto.setAppid(crosstownAssignOrderParam.getAppid());
            operateLogDto.setUuid(StringUtils.buildUUID());
            operateLogDto.setOperationUserIp(crosstownAssignOrderParam.getUserip());
            sysBusinessOperateLogService.add(operateLogDto);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private ResponseData<Map> setAssignTarget(String targetMainOrderUuid) {
        Map paras = new HashMap(16);
        //获取被指派订单
        paras.put("uuid", targetMainOrderUuid);
        OrderDto targetMainOrder = orderMapper.list(paras).get(0);
        if (null == targetMainOrder) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取被指派订单信息失败");
        }
        //获取被指派订单详情
        paras.clear();
        paras.put("orderUuid", targetMainOrderUuid);
        OrderDetailDto targeMainOrderDetail = (OrderDetailDto) orderDetailService.get(paras).getData();
        if (targeMainOrderDetail == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取被指派订单详情失败");
        }
        //获取被指派订单价格表
        paras.clear();
        paras.put("orderUuid", targetMainOrderUuid);
        OrderFareDto targetMainOrderFare = (OrderFareDto) orderFareService.get(paras).getData();
        if (targetMainOrderFare == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取被指派订单价格失败");
        }

        /**订单&司机信息回传（此处由于对象新建无法、并非对象引用传递）**/
        Map temp = new HashMap();
        temp.put("targetMainOrder", targetMainOrder);
        temp.put("targeMainOrderDetail", targeMainOrderDetail);
        temp.put("targetMainOrderFare", targetMainOrderFare);
        temp.put("targetDriverUuid", targetMainOrder.getActualDriverUuid());
        return ResponseData.buildSuccessResponse("获取被指派订单信息成功", temp);
    }

    /**
     * <p>推送订单给所有司机</p>
     *
     * @param orderDto       订单信息
     * @param orderDetailDto 订单详情
     */
    private ResponseData<Boolean> pushNewOrderToDriver(OrderDto orderDto, OrderDetailDto orderDetailDto, String carModelValuationUuid) {
        Map<String, Object> paramsMap = MapUtils.build();
        paramsMap.put("districtUuid", orderDetailDto.getOriginCityUuid());
        paramsMap.put("businessType", orderDto.getTypeModule());
        ResponseData<SysAssignConfigDto> responseWrapper = sysAssignConfigService.get(paramsMap);
        if (!responseWrapper.isSuccess() || responseWrapper.getData() == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到实时单抢单半径");
        }
        SysAssignConfigDto sysAssignConfigDto = responseWrapper.getData();
        CyclePushOrderThread pushOrderThread = new CyclePushOrderThread(orderDto, orderDetailDto, carModelValuationUuid,
                sysAssignConfigDto.getFixedRadius().intValue() * 1000);
        ScheduledFuture<?> scheduledFuture = grabScheduleService.scheduleAtFixedRate(()->{
            //订单状态不合法停止定时任务线程
            if (!isValid(orderDto.getUuid())) {
                log.info("定时派单线程-结束线程-原因[订单状态改变]-订单[" + orderDto.getUuid() + "]");
                cancelScheduleTask(orderDto.getUuid());
                return;
            }
            pushOrderThread.run();
        }, 0, 30, TimeUnit.SECONDS);
        scheduledFuturePool.put(orderDto.getUuid(), scheduledFuture);
        return ResponseData.buildSuccessResponse("新订单推送司机成功", Boolean.TRUE);
    }

    void handleOnAssignDriverSuccess(List<String> targetUuids, DriverDto driverDto, OrderDto orderDto,
                                     OrderDetailDto orderDetailDto, String carModelValuationUuid) {
        //封装推送的内容
        PushContent pushContent = PushContent.newInstance4Dri(orderDto.getAppid(), PushContent.ORDER_DISTRIBUTE,
                OrderPushHelper.buildPushMap(orderDto, orderDetailDto));
        //推送新增订单给司机
        pushService.sendMessageByList(targetUuids, pushContent);
        //直接执行司机接单业务
        updGrabAssign(orderDto, driverDto, carModelValuationUuid);
        //推乘客
        Map<String, Object> map = MapUtils.build();
        map.put("title", "司机接单");
        map.put("content", "司机已接单");
        map.put("orderUuid", orderDto.getUuid());
        map.put("orderType", orderDto.getTypeModule());
        pushContent = PushContent.newInstance4Pas(orderDto.getAppid(), PushContent.ORDER_DRIVER_TAKE, map);
        pushService.sendMessage(orderDto.getPassengerUuid(), pushContent);
        //新增隐私绑定
        String actualPasMob = orderDetailDto.getActualPasMob();
        log.info("开始隐私号绑定，orderUuid:{}", orderDto.getUuid());
        SecretNoParam secretNoParam = new SecretNoParam();
        secretNoParam.setAppid(orderDto.getAppid());
        secretNoParam.setOrderUuid(orderDto.getUuid());
        secretNoParam.setPassengerMobile(actualPasMob);
        secretNoParam.setDriverMobile(driverDto.getMobile());
        ResponseData<String> addBingding = orderSecretNoService.addBingding(secretNoParam);
        if (addBingding.isSuccess() && addBingding.getData() != null) {
            actualPasMob = addBingding.getData();
        }
        // 发送短信/推送给司机
        CompletableFuture.runAsync(new CyclePushMessage(pushService, driverDto, orderDetailDto, actualPasMob));

        // 实时单派送时统计空驶里程
        if (CommonConstant.TYPE_TIME_REAL_TIME == orderDto.getTypeTime()) {
            ThreadExecutorUtils.execute(new DriverStatusCycleRunnable(
                    driverStatusCycleService,
                    locationService,
                    orderDto.getAppid(),
                    driverDto.getUuid(), orderDto.getUuid(),
                    driverDto.getCarUuid(),
                    DriverStatusCycleDto.ACTION_LEAVE));
        }
        //保存静态数据
        saveOrUpdateStaticDataOnOrderMatch(orderDto);
        //分享给紧急联系人
        OrderPushHelper.passengerEmergencyPush(orderDto, orderDetailDto, driverDto, carService.get(driverDto.getCarUuid()).getData());
    }

    /**
     * 司机接单业务
     *
     * @param orderDto
     * @param driverDto
     * @return
     */
    private boolean updGrabAssign(OrderDto orderDto, DriverDto driverDto, String carModelValuationUuid) {
        //更新订单主表
        OrderDto orderParam = new OrderDto();
        orderParam.setUuid(orderDto.getUuid());
        //即时订单，去接乘客
        orderParam.setSubStatus(OrderConstant.ORDER_STATUS_GO);
        orderParam.setMainStatus(OrderConstant.ORDER_MAIN_STATUS_DOING);
        orderParam.setActualDriverUuid(driverDto.getUuid());
        orderParam.setCarUuid(driverDto.getCarUuid());
        orderParam.setUpdateOn(new Date());
        orderParam.setDistributeTime(new Date());
        saveOrUpdate(orderParam);
        //新增 orderFare 记录,有存在记录则更改
        OrderFareDto fareParam = new OrderFareDto();
        fareParam.setCarModelValuationUuid(carModelValuationUuid);
        fareParam.setDriReceiveTime(new Date());
        //实时订单，设置司机出发时间
        if (orderDto.getTypeTime() == CommonConstant.TYPE_TIME_REAL_TIME) {
            fareParam.setDriDepartTime(new Date());
        }
        ResponseData<OrderFareDto> findByOrderUuid = orderFareService.findByOrderUuid(orderDto.getUuid());
        if (findByOrderUuid.isSuccess() && findByOrderUuid.getData() != null) {
            fareParam.setUuid(findByOrderUuid.getData().getUuid());
            fareParam.setOrderUuid(findByOrderUuid.getData().getOrderUuid());
        }
        orderFareService.saveOrUpdate(fareParam);
        //增加司机的累计接单数
        DriverDto updDriverDto = new DriverDto();
        updDriverDto.setOrderCount(driverDto.getOrderCount() == null ? 1 : driverDto.getOrderCount() + 1);
        updDriverDto.setUuid(driverDto.getUuid());
        driverService.edit(updDriverDto);
        return true;
    }

    /**
     * 派单订单相关处理
     *
     * @param crosstownAssignOrderParam
     * @return
     */
    private ResponseData assignOrderHandle(CrosstownAssignOrderParam crosstownAssignOrderParam) {
        OrderDto curOrder = crosstownAssignOrderParam.getCurrentOrderDto();
        OrderDto targetMainOrder = crosstownAssignOrderParam.getTargetMainOrderDto();
        OrderDto curMainOrder = crosstownAssignOrderParam.getCurrentMainOrderDto();
        OrderDetailDto curOrderDetail = crosstownAssignOrderParam.getCurrentOrderDetailDto();
        //是否是小件订单
        boolean isParcelOrder = curOrder.getTypeModule() == CommonConstant.BUSINESS_TYPE_PARCEL;
        //创建主订单（按订单指派则更新）
        //主订单
        ResponseData createOrderResult = createCrosstownOrder(crosstownAssignOrderParam);
        if (!createOrderResult.isSuccess()) {
            return createOrderResult;
        }
        //司机退出排队
        //退出服务范围包含某个点（位置坐标）的所有起点排队 —— 此处以乘客订单坐标为判断标准
//        Coordinate coordinate = new Coordinate();
//        coordinate.setLng(curOrderDetail.getOriginLng());
//        coordinate.setLat(curOrderDetail.getOriginLat());
//        driverQueueService.quit(crosstownAssignOrderParam.getTargetDriverUuid(), coordinate);
        //操作订单司机时，更新隐私绑定
//        String privacyMobile = updateSecretNoB(curOrderDetail.getActualPasMob(), crosstownAssignOrderParam.getDriverMobile(), curOrder.getUuid(),
//                curOrder.getAppid());

        //消息推送
        //司机：收到派单推送
        pushService.sendMessage(crosstownAssignOrderParam.getTargetDriverUuid(), PushContentUtils.crosstownAssignToDriver(crosstownAssignOrderParam));
        //乘客：派单成功通知
        pushService.sendMessage(curOrder.getPassengerUuid(), PushContentUtils.crosstownAssignToPassener(curOrder.getUuid(), curOrder.getTypeModule(), curOrder.getAppid()));

        //推送拼车订单更新
        CrosstownOrderParam crosstownOrderParam = new CrosstownOrderParam();
        crosstownOrderParam.setOrderUuid(curOrder.getUuid());
        crosstownOrderParam.setMainOrderUuid(crosstownAssignOrderParam.getTargetMainOrderUuid());
        crosstownOrderProcessor.pushOtherPassenger(crosstownOrderParam);
        //司机短信
        SendMessageUtils.generalSend(crosstownAssignOrderParam.getDriverMobile(), MessageContentUtils.joinAssignDriverMsg(curOrderDetail, isParcelOrder), curOrder.getAppid());
        //乘客短信
        SendMessageUtils.generalSend(crosstownAssignOrderParam.getCurrentOrderDetailDto().getActualPasMob(), MessageContentUtils.joinAssignPassengerMsg(crosstownAssignOrderParam.getDriverMobile(), crosstownAssignOrderParam.getPlateNum(), isParcelOrder), curOrder.getAppid());
        if (curMainOrder != null) {
            saveOrUpdateStaticDataOnOrderMatch(curMainOrder);
        }
        if (curOrder != null) {
            saveOrUpdateStaticDataOnOrderMatch(curOrder);
        }
        if (targetMainOrder != null) {
            saveOrUpdateStaticDataOnOrderMatch(targetMainOrder);
        }
        return ResponseData.buildSuccessResponse("派单成功");
    }

    /**
     * 派单业务校验
     */
    private ResponseData<Void> assignBusinessVerify(CrosstownAssignOrderParam assignParam) {
        boolean isParcelOrder = assignParam.getCurrentOrderDto().getTypeModule() == CommonConstant.BUSINESS_TYPE_PARCEL;
        SysWayDto systemWayDto = assignParam.getSysWayDto();
        //对已选择的主单进行校验
        log.info("后台派单主单id{}", assignParam.getTargetMainOrderUuid());
        if (StringUtils.isNotEmpty(assignParam.getTargetMainOrderUuid())) {
            //if (!isParcelOrder && assignParam.getResNum() < assignParam.getCurrentOrderDto().getSeatNum()) {
            //    return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "派单失败：司机在该路线的行程座位不足");
            //}
            //出发时间校验
            List<Date> subDeparTimes = orderMapper.findSubDeparTime(assignParam.getTargetMainOrderUuid());
            if (null == subDeparTimes || subDeparTimes.isEmpty()) {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取司机当前路线的行程子订单异常");
            }

            //获取司机在该路线下的跨城小件数量
            int parcelOrderNum = Optional.ofNullable(assignParam.getTargetParcelOrderNum()).orElse(0);
            //获取线路司机小件订单数量限制
            int parcelNumLimit = Optional.ofNullable(systemWayDto.getParcelNumLimit()).orElse(1);
            if (isParcelOrder && parcelOrderNum >= parcelNumLimit) {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "超过司机可接跨城小件订单数量限制，无法指派！");
            }
//            //获取跨城小件经营规则 跨城小件是否可以包车 包车是否可以下跨城小件
//            boolean parcelCanChartered = false;
//            boolean charteredCanParcel = false;
//            if (systemWayDto.getParcelManageRule() != null) {
//                try {
//                    JsonObject parcelManageJson = new Gson().fromJson(systemWayDto.getParcelManageRule(), JsonObject.class);
//                    parcelCanChartered = parcelManageJson.get("parcelCanChartered").getAsBoolean();
//                    charteredCanParcel = parcelManageJson.get("charteredCanParcel").getAsBoolean();
//                } catch (Exception e) {
//                    log.error("JsonUtils readNode error.{}", systemWayDto.getParcelManageRule(), e);
//                }
//            }
//            //包车校验 判断是否有跨城小件订单 = 总订单 - 跨城小件  有跨城订单时，判断有跨城小件订单是否可以下包车订单
//            if ((null != subDeparTimes && !subDeparTimes.isEmpty()) && assignParam.getCurrentOrderDto().getTypeJoin() == CommonConstant.ORDER_TYPE_JOIN_CHARTERED) {
//                if (parcelOrderNum < subDeparTimes.size()) {
//                    return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "派单失败：司机在该路线已有拼车订单,无法指派包车订单");
//                } else if (parcelOrderNum == subDeparTimes.size() && !parcelCanChartered) {
//                    return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "派单失败：该路线不允许对已有跨城小件订单的司机指派包车订单");
//                }
//            } else if ((null != subDeparTimes && !subDeparTimes.isEmpty()) && isParcelOrder && assignParam.getTargetTypeJoin() == CommonConstant.ORDER_TYPE_JOIN_CHARTERED) {
//                //跨城小件校验 当前指派司机的订单是否为包车订单 若为包车订单 判断是否可以再下跨城小件订单
//                if (!charteredCanParcel) {
//                    return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "派单失败：该路线不允许对已有包车订单的司机指派跨城小件订单");
//                }
//            }

            Date deparStartTime = subDeparTimes.get(0);
            Date deparEndTime = subDeparTimes.get(subDeparTimes.size() - 1);
            int assignConfineMinutes = Optional.ofNullable(systemWayDto.getAssignConfineMinutes()).orElse(0);
            Date startConfineTime = CalendarUtil.minutesMinus(deparEndTime, assignConfineMinutes);
            Date endConfineTime = CalendarUtil.minutesPlus(deparStartTime, assignConfineMinutes);
            if (assignParam.getCurrentOrderDetailDto().getDeparTime().after(endConfineTime) || assignParam.getCurrentOrderDetailDto().getDeparTime().before(startConfineTime)) {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "派单失败：当前订单出发时间与司机在该路线行程不匹配");
            }
        }
        //获取司机信息、车辆详细信息
        DriverDto driver = driverService.get(assignParam.getTargetDriverUuid()).getData();
        if (driver == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取司机信息失败");
        }
        //获取司机车辆信息
        CarDto car = carService.get(driver.getCarUuid()).getData();
        if (car == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取司机车辆信息失败");
        }
        assignParam.setSeats(car.getSeats());
        assignParam.setCarUuid(car.getUuid());
        assignParam.setDriverMobile(driver.getMobile());
        assignParam.setPlateNum(car.getPlateNum());
        assignParam.setCarModelUuid(car.getCarModelUuid());
        //获取司机所在公司指派路线
        Map<String, Object> map = MapUtils.build();
        map.put("organizationUuid", driver.getCompanyUuid());
        map.put("type", CommonConstant.BUSINESS_TYPE_POOL);
        if (isParcelOrder) {
            map.put("parcelStatus", CommonConstant.STATUS_OPENED);
        } else {
            map.put("status", CommonConstant.STATUS_OPENED);
        }
        ResponseData<List<BusinessDetailVo>> getBusinessDetail = sysBusinessCityService.getBusinessDetail(map);
        if (!getBusinessDetail.isSuccess() || CollectionUtils.isEmpty(getBusinessDetail.getData())) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "派单失败：获取司机业务开通路线失败");
        }
        boolean isOpen = getBusinessDetail.getData().get(0).getResources().stream().anyMatch(resourceVo ->
                resourceVo != null && systemWayDto.getUuid().equals(resourceVo.getUuid()));
        if (!isOpen) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "派单失败：司机未开通当前订单业务线路");
        }
        //车辆座位数校验
        if (!isParcelOrder && (null != car.getSeats() ? car.getSeats() : 0) < assignParam.getCurrentOrderDetailDto().getActualPasNum()) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "派单失败：被指派司机车辆座位不足");
        }
        //派单锁定校验
        return assignLockVerify(assignParam);
    }

    /**
     * 派单锁定校验
     *
     * @param assignParam
     * @return
     */
    private ResponseData<Void> assignLockVerify(CrosstownAssignOrderParam assignParam) {
        Long needNum;
        String lockDriverKey;
        //小件锁
        if (assignParam.getCurrentOrderDto().getTypeModule() == CommonConstant.BUSINESS_TYPE_PARCEL) {
            lockDriverKey = ASSIGN_DRIVER_LOCK + "parcel" + assignParam.getTargetDriverUuid() + assignParam.getTargetMainOrderUuid();
            needNum = redisStringCacheService.incr(lockDriverKey);
            redisStringCacheService.expire(lockDriverKey, 2, TimeUnit.SECONDS);
            int parcelNumLimit = Optional.ofNullable(assignParam.getSysWayDto().getParcelNumLimit()).orElse(1);
            //司机有订单时 多个司机同时通过校验 判断订单数是否超过小件可接数量 司机无订单时 判断司机是否已被占用
            if (StringUtils.isNotEmpty(assignParam.getTargetMainOrderUuid())) {
                //订单已有的小件数量
                Integer parcelNum = assignParam.getTargetParcelOrderNum();
                if (needNum + parcelNum > parcelNumLimit) {
                    log.info("小件订单{}被锁定，超过小件限制，无法派单", assignParam.getCurrentOrderUuid());
                    return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "当前司机可接跨城小件订单数量已达到限制，无法继续指派！");
                }
            } else {
                if (needNum > 1) {
                    log.info("小件订单{}派单司机{}被已被锁定", assignParam.getCurrentOrderUuid(), assignParam.getTargetDriverUuid());
                    return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "司机已被锁定,请刷新");
                }
            }
        } else {
            //拼车锁
            Integer actualNum = assignParam.getCurrentOrderDto().getSeatNum();
            lockDriverKey = ASSIGN_DRIVER_LOCK + "usrCar" + assignParam.getTargetDriverUuid() + assignParam.getTargetMainOrderUuid();
            needNum = redisStringCacheService.incr(lockDriverKey);
            redisStringCacheService.expire(lockDriverKey, 2, TimeUnit.SECONDS);
            log.info("拼车订单key{} needNum{}", lockDriverKey, needNum);
            //司机有订单时 多个司机同时通过校验 判断订单数是否超过司机座位 司机无订单时  判断司机是否已被占用
            if (StringUtils.isNotEmpty(assignParam.getTargetMainOrderUuid())) {
                //若乘客所需的座位数大于1时 需要算上实际需要的座位数
                needNum = actualNum > 1 ? (needNum - 1 + actualNum) : needNum;
                if (needNum > assignParam.getResNum()) {
                    log.info("拼车订单{}被锁定，司机座位不足，无法派单needNum{}", assignParam.getCurrentOrderUuid(), needNum);
                    return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "司机座位不足");
                }
            } else {
                if (needNum > actualNum) {
                    log.info("拼车订单{}派单司机{}被已被锁定,needNum{}", assignParam.getCurrentOrderUuid(), assignParam.getTargetDriverUuid(), needNum);
                    return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "司机已被锁定,请刷新");
                }
            }
        }
        return ResponseData.buildSuccessResponse("校验成功", null);
    }

    /**
     * 跨城获取排队中司机
     */
    private void getQueueDriver(CrosstownAssignOrderParam crosstownAssignOrderParam) {
        Map<String, Object> paramMap = MapUtils.build();
        OrderDto currentOrderDto = crosstownAssignOrderParam.getCurrentOrderDto();
        OrderDetailDto currentOrderDetailDto = crosstownAssignOrderParam.getCurrentOrderDetailDto();
        paramMap.put("appid", currentOrderDto.getAppid());
        paramMap.put("wayUuid", currentOrderDto.getWayUuid());
        //出发地经纬度
        Coordinate coordinate = new Coordinate();
        coordinate.setLat(currentOrderDetailDto.getOriginLat());
        coordinate.setLng(currentOrderDetailDto.getOriginLng());
        //拼车需要考虑车型
        if (currentOrderDto.getTypeModule() == CommonConstant.BUSINESS_TYPE_POOL) {
            paramMap.put("carModelUuid", currentOrderDto.getCarModelUuid());
        }
        paramMap.put("coordinate", coordinate);
        //首单派单距离
        paramMap.put("assignRadius", crosstownAssignOrderParam.getSysAssignConfigDto().getFirstAssignDistance());
        //下单所需座位数
        paramMap.put("seatNum", currentOrderDetailDto.getAdultNum());
        //只过滤没有订单的司机
        paramMap.put("noOrder", 1);
        log.info("订单:{} 查找排队中司机", crosstownAssignOrderParam.getCurrentOrderUuid());

        ResponseData<List<QueueDriverVo>> queryDriverRsd = driverQueueService.queryQueueDriver(paramMap);
        crosstownAssignOrderParam.setQueueDriverList(queryDriverRsd.getData());
        if (crosstownAssignOrderParam.getQueueDriverList() == null || crosstownAssignOrderParam.getQueueDriverList().size() == 0) {
            log.info("订单:{} 未找到排队中司机,原因:{}", crosstownAssignOrderParam.getCurrentOrderUuid(), queryDriverRsd.getMsg());
        }
    }

    /**
     * 跨城获取相同线路待出发司机
     */
    private void getWaitStartOrder(CrosstownAssignOrderParam crosstownAssignOrderParam) {
        OrderDto curOrder = crosstownAssignOrderParam.getCurrentOrderDto();
        OrderDetailDto curOrderDetail = crosstownAssignOrderParam.getCurrentOrderDetailDto();

        Map<String, Object> paramMap = MapUtils.build();
        paramMap.put("appid", curOrder.getAppid());
        paramMap.put("wayUuid", curOrder.getWayUuid());
        //拼车需要考虑车型 座位数
        if (curOrder.getTypeModule() == CommonConstant.BUSINESS_TYPE_POOL) {
            paramMap.put("carModelUuid", curOrder.getCarModelUuid());
            paramMap.put("seatNum", curOrderDetail.getActualPasNum());
        } else if (curOrder.getTypeModule() == CommonConstant.BUSINESS_TYPE_PARCEL) {
            //小件不可指派给包车订单
            paramMap.put("exclusiveChartered", 1);
        }
        paramMap.put("deparTime", curOrderDetail.getDeparTime());
        //机场专线与普通拼车不互通
        paramMap.put("orderDemand", curOrder.getOrderDemand());
        //由于二人快车特殊性 当二人快车时 只二人快车待出发订单 并且不接小件单
        List<Integer> typeJoinList = new ArrayList<>();
        if (curOrder.getTypeJoin() == CommonConstant.ORDER_TYPE_JOIN_TWO_PERSONS) {
            typeJoinList.add(CommonConstant.ORDER_TYPE_JOIN_TWO_PERSONS);
        } else {
            typeJoinList.add(CommonConstant.ORDER_TYPE_JOIN_ORDINARY);
            typeJoinList.add(CommonConstant.ORDER_TYPE_JOIN_PARCEL);
        }
        paramMap.put("typeJoinList", typeJoinList);
        log.info("订单:{} 查找行程中司机参数appid：{},wayUuid：{},carModelUuid:{},seatNum:{},deparTime:{}",
                crosstownAssignOrderParam.getCurrentOrderUuid(), curOrder.getAppid(), curOrder.getWayUuid(), curOrder.getCarModelUuid(),
                curOrderDetail.getActualPasNum(), curOrderDetail.getDeparTime());
        List<CrosstownOrderAssignVo> crosstownOrderList = orderMapper.getWaitStartOrder(paramMap);
        log.info("订单:{} 查找行程中司机结果{}", crosstownAssignOrderParam.getCurrentOrderUuid(), crosstownOrderList.size());
        if (crosstownOrderList == null || crosstownOrderList.size() == 0) {
            return;
        }
        //计算权重
        SysAssignConfigDto assginConfig = crosstownAssignOrderParam.getSysAssignConfigDto();
        List<CrosstownOrderAssignVo> resultList = new ArrayList<>();
        for (CrosstownOrderAssignVo crosstownOrder : crosstownOrderList) {
            Double weightScore = crosstownOrderProcessor.calWeightScore(assginConfig, curOrderDetail, crosstownOrder.getResNum(), crosstownOrder.getAllPassengerOrderInfoList());
            log.info("主订单：{} 权重得分：{} 系统配置权重分数:{}", crosstownOrder.getMainOrderUuid(), weightScore, assginConfig.getMatchRateThreshold());
            if (weightScore >= assginConfig.getMatchRateThreshold()) {
                crosstownOrder.setWeightScore(weightScore);
                resultList.add(crosstownOrder);
            }
        }
        //按照权重得分降序
        Collections.sort(resultList, (a, b) -> b.getWeightScore().compareTo(a.getWeightScore()));
        //待出发订单放入参数中 等待下一步派单动作
        crosstownAssignOrderParam.setWaitStartOrderList(resultList);
    }


    /**
     * 跨城派单信息获取
     */
    private ResponseData<Boolean> getCrosstownAssignInfo(CrosstownAssignOrderParam crosstownAssignOrderParam) {
        Map<String, Object> paraMap = new HashMap<>(16);
        //获取当前订单
        paraMap.put("uuid", crosstownAssignOrderParam.getCurrentOrderUuid());
        OrderDto orderDto = orderMapper.list(paraMap).get(0);

        if (null == orderDto) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取当前订单信息失败");
        }
        if (orderDto.getJoinStatus() > 500) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "订单已完成，请刷新订单信息！");
        }
        if (orderDto.getCloseStatus() != null && orderDto.getCloseStatus() == OrderConstant.ORDER_CLOSE_STATUS_CLOSED) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "订单已关闭，请刷新订单信息！");
        }
        if (StringUtils.isNotEmpty(crosstownAssignOrderParam.getCurDriverUuid())) {
            if (crosstownAssignOrderParam.getCurDriverUuid().equals(crosstownAssignOrderParam.getTargetDriverUuid())) {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "请勿指派给相同司机！");
            }
        } else {
            if (StringUtils.isNotEmpty(orderDto.getActualDriverUuid())) {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "订单已被指派，请刷新订单信息！");
            }
        }

        //获取当前主订单
        if (StringUtils.isNotEmpty(orderDto.getMainOrderUuid())) {
            OrderDto curMainOrder = orderMapper.list(MapUtils.build("uuid", orderDto.getMainOrderUuid())).get(0);
            if (null == curMainOrder) {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取当前订单（原订单）信息失败");
            }
            crosstownAssignOrderParam.setCurrentMainOrderDto(curMainOrder);
        }
        //获取订单详情
        paraMap.clear();
        paraMap.put("orderUuid", crosstownAssignOrderParam.getCurrentOrderUuid());
        OrderDetailDto orderDetailDto = orderDetailService.get(paraMap).getData();
        if (orderDetailDto == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取订单详情失败");
        }
        //获取订单价格表
        OrderFareDto orderFareDto = orderFareService.get(paraMap).getData();
        if (orderFareDto == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取订单价格失败");
        }
        //获取线路信息
        ResponseData<SysWayDto> wayRS = sysWayService.get(orderDto.getWayUuid());
        if (!wayRS.isSuccess()) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取订单路线失败");
        }
        SysWayDto systemWayDto = wayRS.getData();

        //获取跨城派单规则
        SysAssignConfigDto sysAssignConfigDto = getCrosstownAssignConfig(orderDetailDto.getOriginCityUuid(), orderDto.getAppid());
        if (sysAssignConfigDto == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取跨城派单规则失败");
        }

        //将相关信息传回
        crosstownAssignOrderParam.setCurrentOrderDto(orderDto);
        crosstownAssignOrderParam.setCurrentOrderDetailDto(orderDetailDto);
        crosstownAssignOrderParam.setCurrentOrderFareDto(orderFareDto);
        crosstownAssignOrderParam.setSysWayDto(systemWayDto);
        crosstownAssignOrderParam.setSysAssignConfigDto(sysAssignConfigDto);

        return ResponseData.buildSuccessResponse("获取成功", Boolean.TRUE);
    }

    /**
     * 获取跨城派单配置
     */
    private SysAssignConfigDto getCrosstownAssignConfig(String originCityUuid, String appid) {
        Map<String, Object> paraMap = new HashMap<>();
        paraMap.put("districtUuid", originCityUuid);
        paraMap.put("businessType", CommonConstant.BUSINESS_TYPE_POOL);
        paraMap.put("appid", appid);
        return sysAssignConfigService.get(paraMap).getData();
    }

    /**
     * 不执行自动派单 处理订单预约信息
     */
    private ResponseData notAutoAssignHandleOrder(CrosstownAssignOrderParam crosstownAssignOrderParam, boolean canPush) {
        //有效预约时间判断
        if (crosstownAssignOrderParam.getCurrentOrderDetailDto().getDeparTime().after(CalendarUtil.hoursPlus(new Date(),
                crosstownAssignOrderParam.getSysWayDto().getValidSubMinutes()))) {
            // 直接进入预约成功-待后台手动派单 流程
            orderJoinService.subscribeJoinOrder(crosstownAssignOrderParam.getCurrentOrderUuid(), "SYSTEM_AUTO");
        } else {
            //消息推送：提示订单已提交，等待客服安排（时限30分钟，之后由定时器出发超时，并再次推送提醒）
            //乘客：预约中
            List<String> targetUuids = Arrays.asList(crosstownAssignOrderParam.getCurrentOrderDto().getPassengerUuid());
            Map<String, Object> data = MapUtils.build();
            data.put("orderUuid", crosstownAssignOrderParam.getCurrentOrderDto().getUuid());
            data.put("title", "提示");
            data.put("content", "您的订单已提交成功。我们将尽快确认订单，请您耐心等待。");
            data.put("moduleType", crosstownAssignOrderParam.getCurrentOrderDto().getTypeModule());
            PushContent pushContentByAssignedOrder = PushContent.newInstance4Pas(crosstownAssignOrderParam.getCurrentOrderDto().getAppid(), PushContent.ORDER_JOIN_PAS_SUBING, data);
            pushService.sendMessageByList(targetUuids, pushContentByAssignedOrder);
        }
        //自动派单关闭时 不推送司机
        if (canPush) {
            try {
                //推送排队中司机
                InformThreadPoolUtil.execute(() -> pushQueueDriver(crosstownAssignOrderParam));
            } catch (Exception e) {
                log.info("订单:{} 推送出现异常,{}", crosstownAssignOrderParam.getCurrentOrderUuid(), e);
            }
        }
        if (OrderConstant.ORDER_SOURCE_ADMIN != crosstownAssignOrderParam.getCurrentOrderDto().getSource()) {
            // 管理后台推送
            Map<String, Object> data = MapUtils.build();
            data.put("orderUuid", crosstownAssignOrderParam.getCurrentOrderDto().getUuid());
            data.put("content", "新的跨城订单推送");
            data.put("wayUuid", crosstownAssignOrderParam.getCurrentOrderDto().getWayUuid());
            PushContent pushContentByAdmin = PushContent.newInstance4Admin(crosstownAssignOrderParam.getCurrentOrderDto().getAppid(), PushContent.NEW_JOIN_ORDER_TIP, data);
            pushService.sendMessageByAdmin(pushContentByAdmin);
        }
        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "未指派到司机");
    }

    /**
     * 推送排队中司机
     */
    private void pushQueueDriver(CrosstownAssignOrderParam crosstownAssignOrderParam) {
        OrderDto curOrder = crosstownAssignOrderParam.getCurrentOrderDto();
        OrderDetailDto curOrderDetail = crosstownAssignOrderParam.getCurrentOrderDetailDto();
        //获取排队中司机
        Map<String, Object> paraMap = new HashMap<>();
        paraMap.put("appid", curOrder.getAppid());
        paraMap.put("wayUuid", curOrder.getWayUuid());
        paraMap.put("deparTime", curOrderDetail.getDeparTime());
        paraMap.put("orderUuid", curOrder.getUuid());
        //不推送有进行中订单的司机
        paraMap.put("noUnderWayOrder", 1);
        //下单所需座位数
        paraMap.put("seatNum", curOrderDetail.getAdultNum());
        //拼车需要考虑车型
        if (curOrder.getTypeModule() == CommonConstant.BUSINESS_TYPE_POOL) {
            paraMap.put("carModelUuid", curOrder.getCarModelUuid());
        }

        List<QueueDriverVo> driverList = driverQueueService.queryQueueDriver(paraMap).getData();
        if (driverList != null && driverList.size() > 0) {
            List<String> targetUuidList = new ArrayList<>();
            for (QueueDriverVo queueDriverVo : driverList) {
                targetUuidList.add(queueDriverVo.getDriverUuid());
            }
            PushContent content = PushContent.newInstance4Dri(curOrder.getAppid(), PushContent.ORDER_PUSH, OrderPushHelper.buildPushMap(curOrder, curOrderDetail));
            pushService.sendMessageByList(targetUuidList, content);
        }
    }


    /**
     * 创建跨城订单指派信息
     */
    private ResponseData<String> createCrosstownOrder(CrosstownAssignOrderParam crosstownAssignOrderParam) {
        //取出订单相关信息
        OrderDto curOrder = crosstownAssignOrderParam.getCurrentOrderDto();
        OrderDetailDto curOrderDetail = crosstownAssignOrderParam.getCurrentOrderDetailDto();
        OrderFareDto curOrderFare = crosstownAssignOrderParam.getCurrentOrderFareDto();
        SysWayDto systemWayDto = crosstownAssignOrderParam.getSysWayDto();

        //获取目标主订单信息
        OrderDto targetMainOrder = null;
        OrderDetailDto targeMainOrderDetail = null;
        OrderFareDto targetMainOrderFare = null;
        if (crosstownAssignOrderParam.getTargetMainOrderUuid() != null) {
            ResponseData<Map> targetRS = setAssignTarget(crosstownAssignOrderParam.getTargetMainOrderUuid());
            if (!targetRS.isSuccess()) {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取被指派订单相关信息失败");
            }
            Map<String, Object> map = targetRS.getData();
            targetMainOrder = (OrderDto) map.get("targetMainOrder");
            targeMainOrderDetail = (OrderDetailDto) map.get("targeMainOrderDetail");
            targetMainOrderFare = (OrderFareDto) map.get("targetMainOrderFare");
        }
        //给订单赋值
        return saveAssignCrosstownOrder(curOrder, curOrderDetail, curOrderFare, targetMainOrder, targeMainOrderDetail, targetMainOrderFare, systemWayDto, crosstownAssignOrderParam, null);
    }

    /**
     * 跨城司机抢单
     */
    @Override
    public ResponseData<JsonOrderDetailVo> grabCrosstownOrder(CrosstownAssignOrderParam crosstownAssignOrderParam) {
        //获取跨城相关信息
        ResponseData getOrderInfoRsd = getCrosstownAssignInfo(crosstownAssignOrderParam);
        if (!getOrderInfoRsd.isSuccess()) {
            return getOrderInfoRsd;
        }
        //取出订单相关信息
        OrderDto curOrder = crosstownAssignOrderParam.getCurrentOrderDto();
        OrderDetailDto curOrderDetail = crosstownAssignOrderParam.getCurrentOrderDetailDto();
        OrderFareDto curOrderFare = crosstownAssignOrderParam.getCurrentOrderFareDto();
        SysWayDto systemWayDto = crosstownAssignOrderParam.getSysWayDto();
        if (StringUtils.isNotEmpty(curOrder.getActualDriverUuid())) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "订单已指派给其他司机");
        }
        //获取司机信息、车辆详细信息
        DriverDto driver = driverService.get(crosstownAssignOrderParam.getTargetDriverUuid()).getData();
        if (driver == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取司机信息失败");
        }

        //获取司机车辆信息
        CarDto car = carService.get(MapUtils.build("uuid", driver.getCarUuid())).getData();
        if (car == null) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取司机车辆信息失败");
        }
        crosstownAssignOrderParam.setSeats(car.getSeats());
        crosstownAssignOrderParam.setCarUuid(car.getUuid());
        crosstownAssignOrderParam.setCarModelUuid(car.getCarModelUuid());

        //校验司机待出发的订单 是否满足接单条件 判断满足时是否加入已有主单或者新增一个主单
        ResponseData waitingOrderVerifyRsd = assignWaitingOrderVerify(crosstownAssignOrderParam);
        if (!waitingOrderVerifyRsd.isSuccess()) {
            return waitingOrderVerifyRsd;
        }
        //锁订单
        if (!redisLock.uniqueLock(ASSIGN_ORDER_LOCK + crosstownAssignOrderParam.getCurrentOrderUuid())) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "订单状态已发生改变，请刷新");
        }
        //获取目标主订单信息
        OrderDto targetMainOrder = null;
        OrderDetailDto targeMainOrderDetail = null;
        OrderFareDto targetMainOrderFare = null;
        if (crosstownAssignOrderParam.getTargetMainOrderUuid() != null) {
            ResponseData getMainOrderRsd = setMainOrderInfo(crosstownAssignOrderParam);
            if (!getMainOrderRsd.isSuccess()) {
                return getMainOrderRsd;
            }
            targetMainOrder = crosstownAssignOrderParam.getTargetMainOrderDto();
            targeMainOrderDetail = crosstownAssignOrderParam.getTargetMainOrderDetailDto();
            targetMainOrderFare = crosstownAssignOrderParam.getCurrentOrderFareDto();
        }
        saveAssignCrosstownOrder(curOrder, curOrderDetail, curOrderFare, targetMainOrder, targeMainOrderDetail, targetMainOrderFare,
                systemWayDto, crosstownAssignOrderParam, null);

        //乘客：派单成功通知
        pushService.sendMessage(curOrder.getPassengerUuid(), PushContentUtils.crosstownAssignToPassener(curOrder.getUuid(), curOrder.getTypeModule(), curOrder.getAppid()));
        return orderService.getOrderDetail(crosstownAssignOrderParam.getCurrentOrderUuid(), null);
    }

    /**
     * 保存跨城派单信息
     */
    private ResponseData saveAssignCrosstownOrder(OrderDto curOrder, OrderDetailDto curOrderDetail, OrderFareDto curOrderFare,
                                                  OrderDto targetMainOrder, OrderDetailDto targeMainOrderDetail,
                                                  OrderFareDto targetMainOrderFare, SysWayDto systemWayDto,
                                                  CrosstownAssignOrderParam crosstownAssignOrderParam, Integer scanJoinStatus) {
        //创建订单
        OrderDto orderDto;
        OrderDetailDto orderDetailDto;
        OrderFareDto orderFareDto;

        Date nowDate = new Date();
        boolean isParcelOrder = curOrder.getTypeModule() == CommonConstant.BUSINESS_TYPE_PARCEL;
        //首单&即未指定订单指派
        if (null == targetMainOrder) {
            orderDto = new OrderDto();
            BeanUtils.copyProperties(curOrder, orderDto);
            orderDto.setTypeModule(CommonConstant.BUSINESS_TYPE_POOL);
            orderDto.setUuid(null);
            //注：移除改派情况留下的原主订单UUID
            orderDto.setMainOrderUuid(null);
            orderDto.setOrderNo(null);
            orderDto.setPassengerUuid(null);
            orderDto.setActualDriverUuid(crosstownAssignOrderParam.getTargetDriverUuid());
            orderDto.setCarUuid(crosstownAssignOrderParam.getCarUuid());
            //注：此处主订单车型始终以被指派司机的车型为准、不以乘客订单要求车型为准
            orderDto.setCarModelUuid(crosstownAssignOrderParam.getCarModelUuid());
            orderDto.setTypeMain(OrderConstant.ORDER_TYPE_MAIN);
            orderDto.setSource(0);
            orderDto.setIsAllowAssigned(OrderConstant.ORDER_ALLOW_ASSIGNED_DISABLED);
            orderDto.setDistributeTime(nowDate);
            orderDto.setMatchTime(nowDate);
            orderDto.setJoinStatus(OrderConstant.ORDER_JOIN_STATUS_WAIT_START);
            orderDto.setPassengerLng(null);
            orderDto.setPassengerLat(null);

            //订单详情
            orderDetailDto = new OrderDetailDto();
            BeanUtils.copyProperties(curOrderDetail, orderDetailDto);
            orderDetailDto.setUuid(null);
            orderDetailDto.setDeparTime(curOrderDetail.getDeparTime());
            // 设置线路起终点坐标为主订单起终点坐标
            orderDetailDto.setOriginLng(systemWayDto.getOriginLng());
            orderDetailDto.setOriginLat(systemWayDto.getOriginLat());
            orderDetailDto.setDestLng(systemWayDto.getDestLng());
            orderDetailDto.setDestLat(systemWayDto.getDestLat());
            //小件时 给小件订单数赋值
            if (isParcelOrder) {
                orderDetailDto.setParcelOrderNum(1);
                orderDetailDto.setAdultNum(0);
                orderDetailDto.setResNum(crosstownAssignOrderParam.getSeats());
                orderDetailDto.setParcelPhoto(null);
                orderDetailDto.setParcelInfoName(null);
                orderDetailDto.setReceiptCode(null);
                orderDto.setSeatNum(0);
            } else {
                //计算剩余可坐人数 包车订单派单后剩余可坐人数为0  二人快车为1 拼车按照实际人数计算
                Integer resNum = 0;
                if (curOrder.getTypeJoin() == CommonConstant.ORDER_TYPE_JOIN_TWO_PERSONS) {
                    resNum = 1;
                } else if (curOrder.getTypeJoin() == CommonConstant.ORDER_TYPE_JOIN_ORDINARY) {
                    resNum = crosstownAssignOrderParam.getSeats() - curOrderDetail.getActualPasNum();
                }

                orderDetailDto.setResNum(resNum);
                orderDetailDto.setParcelOrderNum(0);
            }
            //订单价格
            orderFareDto = new OrderFareDto();
            BeanUtils.copyProperties(curOrderFare, orderFareDto);
            orderFareDto.setUuid(null);
            orderFareDto.setDriReceiveTime(nowDate);
        } else {//二次单&改派
            //订单
            orderDto = targetMainOrder;
            //更新订单详情
            orderDetailDto = targeMainOrderDetail;
            //小件时 给小件订单数赋值
            if (isParcelOrder) {
                orderDetailDto.setParcelOrderNum((targeMainOrderDetail.getParcelOrderNum() == null ? 0 : targeMainOrderDetail.getParcelOrderNum()) + 1);
            } else {
                orderDto.setSeatNum(curOrder.getSeatNum() + targetMainOrder.getSeatNum());
                orderDetailDto.setActualPasNum(curOrderDetail.getActualPasNum() + targeMainOrderDetail.getActualPasNum());
                orderDetailDto.setAdultNum(curOrderDetail.getAdultNum() + targeMainOrderDetail.getAdultNum());
                orderDetailDto.setResNum(targeMainOrderDetail.getResNum() - curOrder.getSeatNum());
            }
//            orderDetailDto.setDeparTime(finalDeparTime);
            orderDetailDto.setActualPasMob(null);
            orderDetailDto.setOriginBuscircleUuid(null);
            orderDetailDto.setOriginAddress(null);
            orderDetailDto.setOriginDetailAddress(null);
            orderDetailDto.setDestBuscircleUuid(null);
            orderDetailDto.setDestAddress(null);
            orderDetailDto.setDestDetailAddress(null);
            orderDetailDto.setOriginAreaCode(null);
            orderDetailDto.setRemark(null);
            //订单价格
            orderFareDto = targetMainOrderFare;
            orderFareDto.setPayType(null);
            orderFareDto.setPayTime(null);
            orderFareDto.setUpdateOn(new Date());

        }
        //保存&更新主订单
        String targetMainOrderUuid;
        try {
            targetMainOrderUuid = saveOrderInfo(orderDto, orderDetailDto, orderFareDto);
        } catch (Exception e) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "保存或更新主订单失败");
        }

        //更新子订单
        curOrder.setMainOrderUuid(targetMainOrderUuid);
        //改派处理
        curOrder.setCarUuid(crosstownAssignOrderParam.getCarUuid());
        curOrder.setDistributeTime(new Date());
        curOrder.setMatchTime(new Date());
        curOrder.setValidJson(null);
        if (scanJoinStatus != null) {
            curOrder.setJoinStatus(scanJoinStatus);
        } else {
            curOrder.setJoinStatus(orderDto.getJoinStatus());
        }
        curOrder.setActualDriverUuid(crosstownAssignOrderParam.getTargetDriverUuid());
        //更新子订单
        saveOrUpdate(curOrder);
        return ResponseData.buildSuccessResponse(targetMainOrderUuid);
    }

    /**
     * 取出司机待出发订单 校验时间条件是否满足
     */
    private ResponseData<Void> assignWaitingOrderVerify(CrosstownAssignOrderParam crosstownAssignOrderParam) {
        //取出司机待出发的订单 校验是否满足接单条件 判断满足时是否加入已有主单或者新增一个主单
        List<CrosstownWaitStartOrderVo> waitStartOrderList = orderMapper.getDriverWaitStartOrder(MapUtils.build("driverUuid", crosstownAssignOrderParam.getTargetDriverUuid()));
        Long curDeparTime = crosstownAssignOrderParam.getCurrentOrderDetailDto().getDeparTime().getTime();
        OrderDto curOrderDto = crosstownAssignOrderParam.getCurrentOrderDto();
        for (CrosstownWaitStartOrderVo waitStartOrderVo : waitStartOrderList) {
            //当前订单出发时间与待出发订单最小出发时间之差绝对值
            Long absMinDeparTime = Math.abs((curDeparTime - waitStartOrderVo.getMinDeparTime()) / (1000 * 60));
            Long absMaxDeparTime = Math.abs((curDeparTime - waitStartOrderVo.getMaxDeparTime()) / (1000 * 60));
            //当原订单出发时间与待出发订单出发时间两两时间间隔在时间容忍度之内 可直接加入已有的待出发订单中
            log.info("订单：{} 判断最大出发时间差{}与最小出发时间差{}", crosstownAssignOrderParam.getCurrentOrderDto().getUuid(), absMaxDeparTime, absMinDeparTime);
            if (absMinDeparTime <= waitStartOrderVo.getAssignConfineMinutes() && absMaxDeparTime <= waitStartOrderVo.getAssignConfineMinutes()) {
                if (crosstownAssignOrderParam.getCurrentOrderDto().getSeatNum() > waitStartOrderVo.getResNum()) {
                    return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "待出发订单位置不足，无法接单");
                }
                //扫码下单校验
                if (curOrderDto.getSource() == OrderConstant.ORDER_SOURCE_SCAN_CODE) {
                    if (curOrderDto.getTypeJoin() == CommonConstant.ORDER_TYPE_JOIN_CHARTERED) {
                        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "司机该时间段已有待出发订单，无法选择包车");
                    } else if (curOrderDto.getTypeJoin() == CommonConstant.ORDER_TYPE_JOIN_TWO_PERSONS && waitStartOrderVo.getTypeJoin() != CommonConstant.ORDER_TYPE_JOIN_TWO_PERSONS) {
                        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "司机已有订单非二人快车，请重新选择下单");
                    } else if (!waitStartOrderVo.getWayUuid().equals(curOrderDto.getWayUuid())) {
                        return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "司机该时间段已有其他线路订单");
                    }
                }
                //取出主单ID进行派单 结束循环
                crosstownAssignOrderParam.setTargetMainOrderUuid(waitStartOrderVo.getMainOrderUuid());
                crosstownAssignOrderParam.setResNum(waitStartOrderVo.getResNum());
                break;
            } else {
                //待抢订单与待出发订单时间不接近 判断该订单+线路耗时+时间容忍度 +1小时预留时间 <= 待出发订单最小时间 或者待出发最晚出发时间 + 线路耗时 +1小时预留时间 <= 该订单出发时间
                if ((curDeparTime < waitStartOrderVo.getMinDeparTime() && (curDeparTime / (1000 * 60) + crosstownAssignOrderParam.getSysWayDto().getConsumeMinutes() + crosstownAssignOrderParam.getSysWayDto().getAssignConfineMinutes() + 60) > (waitStartOrderVo.getMinDeparTime() / (1000 * 60)))
                        || (curDeparTime > waitStartOrderVo.getMaxDeparTime() && (waitStartOrderVo.getMaxDeparTime() / (1000 * 60) + waitStartOrderVo.getConsumeMinutes() + 60) > (curDeparTime / (1000 * 60)))) {
                    return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "司机的已有订单存在完成风险，无法接单");
                }
            }
        }
        return ResponseData.buildSuccessResponse("校验通过", null);
    }

    /**
     * 跨城获取主订单信息
     */
    private ResponseData<Boolean> setMainOrderInfo(CrosstownAssignOrderParam crosstownAssignOrderParam) {
        ResponseData<Map> targetRS = setAssignTarget(crosstownAssignOrderParam.getTargetMainOrderUuid());
        if (!targetRS.isSuccess()) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取主订单信息失败");
        }
        Map data = targetRS.getData();
        crosstownAssignOrderParam.setTargetMainOrderDto((OrderDto) data.get("targetMainOrder"));
        crosstownAssignOrderParam.setTargetMainOrderDetailDto((OrderDetailDto) data.get("targeMainOrderDetail"));
        crosstownAssignOrderParam.setTargetMainOrderFareDto((OrderFareDto) data.get("targetMainOrderFare"));
        crosstownAssignOrderParam.setTargetParcelOrderNum(crosstownAssignOrderParam.getTargetMainOrderDetailDto().getParcelOrderNum());
        return ResponseData.buildSuccessResponse("获取主订单信息成功", Boolean.TRUE);
    }

    @Override
    public ResponseData<Boolean> doMergeAssign(MergeAssignParam mergeAssignParam) {
        ResponseData assignInfoRsd = getMargeAssignOrderInfo(mergeAssignParam);
        if (!assignInfoRsd.isSuccess()) {
            //获取失败
            return assignInfoRsd;
        }
        List<AdminChildOrderInfoVo> orderList = mergeAssignParam.getOrderInfoList();
        Date nowDate = new Date();
        SysWayDto sysWayDto = mergeAssignParam.getSysWayDto();
        //创建主订单信息
        OrderDto mainOrderDto = null;
        OrderDetailDto mainOrderDetailDto = null;
        OrderFareDto mainOrderFareDto = null;
        //需要保存的子单集合
        List<OrderDto> curOrderSaveList = new ArrayList<>();
        //是否首单
        boolean isFirstOrder = false;
        for (AdminChildOrderInfoVo orderInfoVo : orderList) {
            //锁订单
            if (!redisLock.uniqueLock(ASSIGN_ORDER_LOCK + orderInfoVo.getOrderUuid(), 2000)) {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "所选订单状态已发生改变，请刷新后重试");
            }
            boolean isParcelOrder = orderInfoVo.getTypeModule() == CommonConstant.BUSINESS_TYPE_PARCEL;
            if (mergeAssignParam.getMainOrderDto() == null) {
                log.info("开始首单派单++++++++++++");
                isFirstOrder = true;
                //首单时，需要锁住司机 待增加司机锁定
                if (!redisLock.uniqueLock(ASSIGN_DRIVER_LOCK + mergeAssignParam.getDriverUuid(), 2000)) {
                    return ResponseData.buildErrorResponse(0, "司机状态已发生变化，请刷新列表");
                }

                Map<String, Object> paraMap = new HashMap();
                paraMap.put("uuid", orderInfoVo.getOrderUuid());
                OrderDto curOrder = orderMapper.list(paraMap).get(0);
                paraMap.clear();
                paraMap.put("orderUuid", orderInfoVo.getOrderUuid());
                OrderDetailDto curOrderDetail = orderDetailMapper.list(paraMap).get(0);
                OrderFareDto curOrderFare = orderFareMapper.list(paraMap).get(0);
                mainOrderDto = new OrderDto();
                BeanUtils.copyProperties(curOrder, mainOrderDto);
                mainOrderDto.setTypeModule(CommonConstant.BUSINESS_TYPE_POOL);
                mainOrderDto.setUuid(null);
                mainOrderDto.setMainOrderUuid(null);
                mainOrderDto.setOrderNo(null);
                mainOrderDto.setPassengerUuid(null);
                mainOrderDto.setActualDriverUuid(mergeAssignParam.getDriverUuid());
                mainOrderDto.setCarUuid(mergeAssignParam.getDriverDto().getCarUuid());
                //注：此处主订单车型始终以被指派司机的车型为准、不以乘客订单要求车型为准
                mainOrderDto.setCarModelUuid(mergeAssignParam.getCarModelUuid());
                mainOrderDto.setTypeMain(OrderConstant.ORDER_TYPE_MAIN);
                mainOrderDto.setSource(0);
                mainOrderDto.setIsAllowAssigned(OrderConstant.ORDER_ALLOW_ASSIGNED_DISABLED);
                mainOrderDto.setDistributeTime(nowDate);
                mainOrderDto.setMatchTime(nowDate);
                mainOrderDto.setJoinStatus(OrderConstant.ORDER_JOIN_STATUS_WAIT_START);
                mainOrderDto.setPassengerLng(null);
                mainOrderDto.setPassengerLat(null);

                //订单详情
                mainOrderDetailDto = new OrderDetailDto();
                BeanUtils.copyProperties(curOrderDetail, mainOrderDetailDto);
                mainOrderDetailDto.setUuid(null);
                mainOrderDetailDto.setDeparTime(orderInfoVo.getDeparTime());
                // 设置线路起终点坐标为主订单起终点坐标
                mainOrderDetailDto.setOriginLng(sysWayDto.getOriginLng());
                mainOrderDetailDto.setOriginLat(sysWayDto.getOriginLat());
                mainOrderDetailDto.setDestLng(sysWayDto.getDestLng());
                mainOrderDetailDto.setDestLat(sysWayDto.getDestLat());
                //小件时 给小件订单数赋值
                if (isParcelOrder) {
                    mainOrderDetailDto.setParcelOrderNum(1);
                    mainOrderDetailDto.setAdultNum(0);
                    mainOrderDetailDto.setResNum(mergeAssignParam.getSeats());
                    mainOrderDetailDto.setParcelPhoto(null);
                    mainOrderDetailDto.setParcelInfoName(null);
                    mainOrderDetailDto.setReceiptCode(null);
                } else {
                    //计算剩余可坐人数 包车订单派单后剩余可坐人数为0  二人快车为1 拼车按照实际人数计算
                    Integer resNum = 0;
                    if (curOrder.getTypeJoin() == CommonConstant.ORDER_TYPE_JOIN_TWO_PERSONS) {
                        resNum = 1;
                    } else if (curOrder.getTypeJoin() == CommonConstant.ORDER_TYPE_JOIN_ORDINARY) {
                        resNum = mergeAssignParam.getSeats() - orderInfoVo.getActualPasNum();
                    }
                    mainOrderDetailDto.setResNum(resNum);
                    mainOrderDetailDto.setParcelOrderNum(0);
                }
                log.info("首单剩余" + mainOrderDetailDto.getResNum());
                //订单价格
                mainOrderFareDto = new OrderFareDto();
                BeanUtils.copyProperties(curOrderFare, mainOrderFareDto);
                mainOrderFareDto.setUuid(null);
                mainOrderFareDto.setDriReceiveTime(nowDate);
                //保存主单信息 剩余订单将合并到同一个主单中
                mergeAssignParam.setMainOrderDto(mainOrderDto);
                mergeAssignParam.setMainOrderDetailDto(mainOrderDetailDto);
                mergeAssignParam.setMainOrderFareDto(mainOrderFareDto);

            } else {
                log.info("开始二次派单++++++++++++");
                //非首单时 需要锁住司机座位或者锁住小件可接数量
                if (!isFirstOrder) {
                    if (isParcelOrder) {
                        if (lockParcelOrderNum(mergeAssignParam.getDriverUuid(), mergeAssignParam.getMainOrderUuid()) > sysWayDto.getParcelNumLimit()) {
                            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "超过司机可接跨城小件订单数量限制，无法指派！");
                        }
                    } else {
                        if (lockJoinOrderNum(mergeAssignParam.getDriverUuid(), mergeAssignParam.getMainOrderUuid()) + mergeAssignParam.getParcelOrderNum() > mergeAssignParam.getMainOrderDetailDto().getResNum()) {
                            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "司机剩余位置不足,请刷新列表");
                        }
                    }
                }
                mainOrderDto = mergeAssignParam.getMainOrderDto();
                //更新订单详情
                mainOrderDetailDto = mergeAssignParam.getMainOrderDetailDto();
                //小件时 给小件订单数赋值
                if (isParcelOrder) {
                    mainOrderDetailDto.setParcelOrderNum((mainOrderDetailDto.getParcelOrderNum() == null ? 0 : mainOrderDetailDto.getParcelOrderNum()) + 1);
                } else {
                    mainOrderDto.setSeatNum(orderInfoVo.getSeatNum() + mainOrderDto.getSeatNum());
                    mainOrderDetailDto.setActualPasNum(orderInfoVo.getActualPasNum() + mainOrderDetailDto.getActualPasNum());
                    mainOrderDetailDto.setAdultNum(orderInfoVo.getAdultNum() + mainOrderDetailDto.getAdultNum());
                    mainOrderDetailDto.setResNum(mainOrderDetailDto.getResNum() - orderInfoVo.getSeatNum());
                }
                // orderDetailDto.setDeparTime(finalDeparTime);
                mainOrderDetailDto.setActualPasMob(null);
                mainOrderDetailDto.setOriginBuscircleUuid(null);
                mainOrderDetailDto.setOriginAddress(null);
                mainOrderDetailDto.setOriginDetailAddress(null);
                mainOrderDetailDto.setDestBuscircleUuid(null);
                mainOrderDetailDto.setDestAddress(null);
                mainOrderDetailDto.setDestDetailAddress(null);
                mainOrderDetailDto.setOriginAreaCode(null);
                mainOrderDetailDto.setRemark(null);
            }

            //更新子订单
            OrderDto curOrder = new OrderDto();
            curOrder.setPassengerUuid(orderInfoVo.getPassengerUuid());
            curOrder.setTypeModule(orderInfoVo.getTypeModule());
            curOrder.setUuid(orderInfoVo.getOrderUuid());
            curOrder.setMainOrderUuid(mainOrderDto.getUuid());
            curOrder.setTypeInteractive(OrderConstant.NEW_ORDER_TYPE_INTERACTIVE_PUSH);
            //改派处理
            curOrder.setCarUuid(mainOrderDto.getCarUuid());
            curOrder.setDistributeTime(new Date());
            curOrder.setMatchTime(new Date());
            curOrder.setValidJson(null);
            curOrder.setJoinStatus(mainOrderDto.getJoinStatus());
            curOrder.setActualDriverUuid(mainOrderDto.getActualDriverUuid());
            curOrder.setUpdateOn(new Date());
            curOrderSaveList.add(curOrder);
        }

        //保存&更新主订单
        String targetMainOrderUuid;
        try {
            targetMainOrderUuid = saveOrderInfo(mainOrderDto, mainOrderDetailDto, mainOrderFareDto);
        } catch (Exception e) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "保存或更新主订单失败");
        }

        for (OrderDto curOrder : curOrderSaveList) {
            curOrder.setMainOrderUuid(targetMainOrderUuid);
            //修复旧订单类型
            orderMapper.edit(curOrder);
            //乘客：派单成功通知
            pushService.sendMessage(curOrder.getPassengerUuid(), PushContentUtils.crosstownAssignToPassener(targetMainOrderUuid, curOrder.getTypeModule(), mainOrderDto.getAppid()));

        }
        //司机：收到派单推送
        pushService.sendMessage(mainOrderDto.getActualDriverUuid(), PushContentUtils.crosstownMargeAssignToDriver(targetMainOrderUuid, mergeAssignParam.getOrderUuidList(), mainOrderDto.getAppid()));

        return ResponseData.buildSuccessResponse("派单成功", true);
    }

    /**
     * 合并派单校验
     */
    private ResponseData getMargeAssignOrderInfo(MergeAssignParam mergeAssignParam) {
        List<AdminChildOrderInfoVo> orderList = orderMapper.getChildOrderInfoById(MapUtils.build("orderUuidList", mergeAssignParam.getOrderUuidList()));
        if (orderList == null || orderList.size() != mergeAssignParam.getOrderUuidList().size()) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取订单信息失败");
        }
        //实际乘车人数
        Integer actualPasNum = 0;
        //跨城小件数量
        Integer parcelOrderNum = 0;
        mergeAssignParam.setOrderInfoList(orderList);
        for (AdminChildOrderInfoVo orderInfoVo : orderList) {
            actualPasNum += orderInfoVo.getActualPasNum();
            if (orderInfoVo.getTypeModule() == CommonConstant.BUSINESS_TYPE_PARCEL) {
                parcelOrderNum += 1;
            }
        }
        mergeAssignParam.setParcelOrderNum(parcelOrderNum);
        //获取线路
        ResponseData<SysWayDto> wayRS = sysWayService.get(MapUtils.build("uuid", orderList.get(0).getWayUuid()));
        if (!wayRS.isSuccess()) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取订单路线失败");
        }
        SysWayDto systemWayDto = wayRS.getData();
        mergeAssignParam.setSysWayDto(systemWayDto);
        //指派到待出发订单时
        if (StringUtils.isNotEmpty(mergeAssignParam.getMainOrderUuid())) {
            if (orderList.get(0).getTypeJoin() == CommonConstant.ORDER_TYPE_JOIN_TWO_PERSONS) {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "二人快车订单只能指派给空车司机！");
            }
            //获取目标主订单信息
            if (mergeAssignParam.getMainOrderUuid() != null) {
                ResponseData<Map> targetRS = setAssignTarget(mergeAssignParam.getMainOrderUuid());
                if (targetRS.isSuccess()) {
                    Map m = targetRS.getData();
                    mergeAssignParam.setMainOrderDto((OrderDto) m.get("targetMainOrder"));
                    mergeAssignParam.setMainOrderDetailDto((OrderDetailDto) m.get("targeMainOrderDetail"));
                    mergeAssignParam.setMainOrderFareDto((OrderFareDto) m.get("targetMainOrderFare"));
                } else {
                    return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取被指派订单相关信息失败");
                }
            }
            if (actualPasNum > mergeAssignParam.getMainOrderDetailDto().getResNum()) {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "司机剩余位置不足");
            }
            if ((parcelOrderNum + mergeAssignParam.getMainOrderDetailDto().getParcelOrderNum()) >= systemWayDto.getParcelNumLimit()) {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "超过司机可接跨城小件订单数量限制，无法指派！");
            }

        }

        if (StringUtils.isNotEmpty(mergeAssignParam.getDriverUuid())) {
            //获取司机信息、车辆详细信息
            DriverDto driver = driverService.get(MapUtils.build("uuid", mergeAssignParam.getDriverUuid())).getData();
            if (driver == null) {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取司机信息失败");
            }
            if (parcelOrderNum > systemWayDto.getParcelNumLimit()) {
                return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "超过司机可接跨城小件订单数量限制，无法指派！");
            }
            CarDto carDto = carService.get(MapUtils.build("uuid", driver.getCarUuid())).getData();
            mergeAssignParam.setDriverDto(driver);
            mergeAssignParam.setSeats(carDto.getSeats());
            mergeAssignParam.setCarModelUuid(carDto.getCarModelUuid());
        }

        return ResponseData.buildSuccessResponse("校验成功");

    }

    @Override
    public ResponseData<JsonOrderDetailVo> doAssignCrosstownOrderAuto(CrosstownAssignOrderParam crosstownAssignOrderParam) {
        //获取跨城订单与线路等相关信息
        ResponseData assignInfoRsd = getCrosstownAssignInfo(crosstownAssignOrderParam);
        if (!assignInfoRsd.isSuccess()) {
            //获取失败
            return assignInfoRsd;
        }
        //派单规则设置手动派单
        if (crosstownAssignOrderParam.getSysAssignConfigDto().getAssignMode() == CommonConstant.CROSSTOWN_ORDER_ASSIGN_MODEL_MANUAL
                || (crosstownAssignOrderParam.getCurrentOrderDto().getTypeModule() == CommonConstant.BUSINESS_TYPE_PARCEL
                && crosstownAssignOrderParam.getSysAssignConfigDto().getParcelAssignMode() == CommonConstant.CROSSTOWN_ORDER_ASSIGN_MODEL_MANUAL)) {
            log.info("订单：{}，自动派单配置未开启", crosstownAssignOrderParam.getCurrentOrderUuid());
            //不执行自动派单 处理订单预约信息 不执行推单
            return notAutoAssignHandleOrder(crosstownAssignOrderParam, false);
        }
        switch (crosstownAssignOrderParam.getCurrentOrderDto().getTypeJoin()) {
            //普通拼车
            case CommonConstant.ORDER_TYPE_JOIN_ORDINARY: {
                //获取待出发订单
                getWaitStartOrder(crosstownAssignOrderParam);
                break;
            }
            //包车
            case CommonConstant.ORDER_TYPE_JOIN_CHARTERED: {
                //包车实时单可以指派排队中司机  预约单不直接指派司机
                if (crosstownAssignOrderParam.getCurrentOrderDto().getTypeTime() == CommonConstant.TYPE_TIME_REAL_TIME) {
                    getQueueDriver(crosstownAssignOrderParam);
                }
                break;
            }
            //小件
            case CommonConstant.ORDER_TYPE_JOIN_PARCEL: {
                //获取待出发订单
                getWaitStartOrder(crosstownAssignOrderParam);
                break;
            }
            //二人快车
            case CommonConstant.ORDER_TYPE_JOIN_TWO_PERSONS: {
                //获取待出发订单
                getWaitStartOrder(crosstownAssignOrderParam);
                break;
            }
            default:
                break;
        }
        //目标司机ID
        String targetDriverUuid = null;
        //目标主单ID
        //是否已经取到司机
        //优先从待出发列表中选出符合条件的司机
        if (crosstownAssignOrderParam.getWaitStartOrderList() != null && crosstownAssignOrderParam.getWaitStartOrderList().size() > 0) {
            for (CrosstownOrderAssignVo crosstownOrder : crosstownAssignOrderParam.getWaitStartOrderList()) {
                crosstownAssignOrderParam.setTargetParcelOrderNum(crosstownOrder.getParcelOrderNum());
                crosstownAssignOrderParam.setResNum(crosstownOrder.getResNum());
                crosstownAssignOrderParam.setTargetDriverUuid(crosstownOrder.getDriverUuid());
                crosstownAssignOrderParam.setTargetMainOrderUuid(crosstownOrder.getMainOrderUuid());
                crosstownAssignOrderParam.setTargetTypeJoin(crosstownOrder.getTypeJoin());

                //进行业务校验 若通过则取出该司机 否则继续下一条订单直到获取到司机获取循环结束
                ResponseData assignResult = assignBusinessVerify(crosstownAssignOrderParam);
                if (assignResult.isSuccess()) {
                    targetDriverUuid = crosstownAssignOrderParam.getTargetDriverUuid();
                    //取出相关主单信息
                    getMainOrderInfo(crosstownAssignOrderParam);
                    break;
                }
                log.info("订单:{} 校验司机信息未通过原因{}", crosstownAssignOrderParam.getCurrentOrderUuid(), assignResult.getMsg());
            }
        }

        //当拼车单或者小件单待出发列表未取到司机 且当订单为实时单时 再获取排队中司机 在下一个流程中继续指派司机
        if (targetDriverUuid == null
                && crosstownAssignOrderParam.getCurrentOrderDto().getTypeJoin() != CommonConstant.ORDER_TYPE_JOIN_CHARTERED
                && crosstownAssignOrderParam.getCurrentOrderDto().getTypeTime() == CommonConstant.TYPE_TIME_REAL_TIME) {
            log.info("订单:{} 自动派单未找到待出发的司机，继续查找排队中司机", crosstownAssignOrderParam.getCurrentOrderUuid());
            getQueueDriver(crosstownAssignOrderParam);
        }

        //待出发列表未得出结果 或者订单为包车单时 从排队中司机选出司机
        if (targetDriverUuid == null && crosstownAssignOrderParam.getQueueDriverList() != null && crosstownAssignOrderParam.getQueueDriverList().size() > 0) {
            for (QueueDriverVo queueDriverVo : crosstownAssignOrderParam.getQueueDriverList()) {
                crosstownAssignOrderParam.setTargetMainOrderUuid(null);
                crosstownAssignOrderParam.setTargetDriverUuid(queueDriverVo.getDriverUuid());
                //进行业务校验 若通过则取出该司机 否则继续下一条订单直到获取到司机获取循环结束
                ResponseData assignResult = assignBusinessVerify(crosstownAssignOrderParam);
                if (assignResult.isSuccess()) {
                    targetDriverUuid = crosstownAssignOrderParam.getTargetDriverUuid();
                    break;
                }
            }
        }
        //未找到符合条件的司机
        if (targetDriverUuid == null) {
            log.info("订单:{} 未执行自动派单", crosstownAssignOrderParam.getCurrentOrderUuid());
            //不执行自动派单 处理订单预约信息 可执行推单
            return notAutoAssignHandleOrder(crosstownAssignOrderParam, true);
        }
        //成功找到派单司机 执行派单订单相关处理
        return assignOrderHandle(crosstownAssignOrderParam);
    }

    /**
     * 派单成功取出主单相关信息
     */
    private void getMainOrderInfo(CrosstownAssignOrderParam assignParam) {
        Map paras = new HashMap();
        //获取被指派订单
        paras.put("uuid", assignParam.getTargetMainOrderUuid());
        assignParam.setTargetMainOrderDto(orderMapper.list(paras).get(0));
        //获取被指派订单详情
        paras.clear();
        paras.put("orderUuid", assignParam.getTargetMainOrderUuid());
        assignParam.setTargetMainOrderDetailDto(orderDetailMapper.list(paras).get(0));
        //获取被指派订单价格表
        assignParam.setTargetMainOrderFareDto(orderFareMapper.list(paras).get(0));
    }


    //小件订单数量锁
    private Long lockParcelOrderNum(String driverUuid, String mainOrderUuid) {
        String lockKey = ASSIGN_DRIVER_LOCK + "parcel" + driverUuid + mainOrderUuid;
        Long incr = redisStringCacheService.incr(lockKey);
        redisStringCacheService.expire(lockKey, 2, TimeUnit.SECONDS);
        return incr;
    }

    //拼车订单数量锁
    private Long lockJoinOrderNum(String driverUuid, String mainOrderUuid) {
        String lockKey = ASSIGN_DRIVER_LOCK + "useCar" + driverUuid + mainOrderUuid;
        Long incr = redisStringCacheService.incr(lockKey);
        redisStringCacheService.expire(lockKey, 2, TimeUnit.SECONDS);
        return incr;
    }

    //跨城订单锁
    private Long lockCrosstownOrder(String orderUuid) {
        String redisKey = ASSIGN_ORDER_LOCK + orderUuid;
        Long incr = redisStringCacheService.incr(redisKey);
        redisStringCacheService.expire(redisKey, 2, TimeUnit.SECONDS);
        return incr;
    }

    @Override
    public ResponseData<Boolean> doScanOrderAssign(CrosstownAssignOrderParam crosstownAssignOrderParam) {
        //获取跨城订单与线路等相关信息
        ResponseData assignInfoRsd = getCrosstownAssignInfo(crosstownAssignOrderParam);
        if (!assignInfoRsd.isSuccess()) {
            //获取失败
            return assignInfoRsd;
        }

        //校验司机待出发的订单 是否满足接单条件 判断满足时是否加入已有主单或者新增一个主单
        if (StringUtils.isEmpty(crosstownAssignOrderParam.getTargetMainOrderUuid())) {
            ResponseData waitingOrderVerifyRsd = assignWaitingOrderVerify(crosstownAssignOrderParam);
            if (!waitingOrderVerifyRsd.isSuccess()) {
                return waitingOrderVerifyRsd;
            }
        }

        //获取原订单信息
        OrderDto curOrder = crosstownAssignOrderParam.getCurrentOrderDto();
        OrderDetailDto curOrderDetail = crosstownAssignOrderParam.getCurrentOrderDetailDto();
        OrderFareDto curOrderFare = crosstownAssignOrderParam.getCurrentOrderFareDto();
        OrderDto curMainOrder = crosstownAssignOrderParam.getCurrentMainOrderDto();
        SysWayDto systemWayDto = crosstownAssignOrderParam.getSysWayDto();

        /*-----------------------------------------派单处理---------------------------------------------*/
        //获取目标主订单信息
        OrderDto targeMainOrder = null;
        OrderDetailDto targeMainOrderDetail = null;
        OrderFareDto targeMainOrderFare = null;
        if (StringUtils.isNotEmpty(crosstownAssignOrderParam.getTargetMainOrderUuid())) {
            ResponseData getMainOrderRsd = setMainOrderInfo(crosstownAssignOrderParam);
            if (!getMainOrderRsd.isSuccess()) {
                return getMainOrderRsd;
            } else {
                targeMainOrder = crosstownAssignOrderParam.getTargetMainOrderDto();
                targeMainOrderDetail = crosstownAssignOrderParam.getTargetMainOrderDetailDto();
                targeMainOrderFare = crosstownAssignOrderParam.getCurrentOrderFareDto();
                crosstownAssignOrderParam.setTargetParcelOrderNum(targeMainOrderDetail.getParcelOrderNum());
            }
        }

        //进行指派业务校验
        ResponseData verifyResultRsd = assignBusinessVerify(crosstownAssignOrderParam);
        if (!verifyResultRsd.isSuccess()) {
            //获取失败
            return verifyResultRsd;
        }

        int joinStatus = OrderConstant.ORDER_JOIN_STATUS_INIT;
        if (OrderConstant.ORDER_PAY_PATTERN_AFTER.equals(curOrder.getPayPattern())) {
            joinStatus = OrderConstant.ORDER_JOIN_STATUS_WAIT_START;
        }
        //创建主订单（按订单指派则更新）
        ResponseData saveRsd = saveAssignCrosstownOrder(curOrder, curOrderDetail, curOrderFare, targeMainOrder, targeMainOrderDetail, targeMainOrderFare,
                systemWayDto, crosstownAssignOrderParam, joinStatus);
        if (!saveRsd.isSuccess()) {
            return saveRsd;
        }
        /*----------------订单相关信息更新结束--------------------*/
        CrosstownOrderParam crosstownOrderParam = new CrosstownOrderParam();
        crosstownOrderParam.setOrderUuid(curOrder.getUuid());
        if (null == curMainOrder) {
            //消息推送
            //司机：收到派单推送
            pushService.sendMessage(crosstownAssignOrderParam.getTargetDriverUuid(), PushContentUtils.crosstownAssignToDriver(crosstownAssignOrderParam));
            crosstownOrderParam.setMainOrderUuid(crosstownAssignOrderParam.getTargetMainOrderUuid());
            crosstownOrderProcessor.pushOtherPassenger(crosstownOrderParam);
        }
        // 返回该子订单信息
        if (curMainOrder != null) {
            saveOrUpdateStaticDataOnOrderMatch(curMainOrder);
        }
        if (curOrder != null) {
            saveOrUpdateStaticDataOnOrderMatch(curOrder);
        }
        if (targeMainOrder != null) {
            saveOrUpdateStaticDataOnOrderMatch(targeMainOrder);
        }
        return ResponseData.buildSuccessResponse("派单成功", null);
    }

}
